HDU 2767 Proving Equivalences(强连通缩点)
2015-11-22 00:22
567 查看
题意:给出一个有向图,不一定连通,问至少加多少有向边可以使其变成连通的。
思路:先跑一遍Tarjan并进行缩点。缩完点后,得到一个DAG,设入度为0的点数位inCnt,出度为0的点数为outCnt,则答案为max(inCnt, outCnt)。注意如果跑完一遍图本身就是强连通的,则直接输出0。
下面证明为什么答案是max(inCnt, outCnt)。
先给出一个有向图。
![](http://img.blog.csdn.net/20151122105947625?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
假如这个是缩完点后的图,那我们如何添最少的变使它变成强连通图呢。
对于这个图,我们可以看到入度为0的点为: 1,2,6,7; 出度为0的点为 4,5,6,7,8。要使图变成强连通的,则显然要使:总的出度数 = 总的入度数,且保证每个点的出度和入度都大于0。那么我们可以先画下面这样的图:
![](http://img.blog.csdn.net/20151122110017904?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
红色箭头表示我们至少要添的有向边。
那么显然,我们只需要把“出”的箭头连到“入”的箭头上,且保证所有红色箭头都有得连接,那么就可以得到一个强连通图。所有“出”的箭头与“入”的箭头对应相连,即我们添的一条有向边是对应至少一条“入”箭头和至少一条“出”箭头,那么显然,添边的数量不会超过max{“入”的箭头数量,“出”的箭头的数量}。这一图中入度为0的点有4个,出度为0的有5个,所以至少添的有向边数为5。下图为其中一种添法。
![](http://img.blog.csdn.net/20151122110038283?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
只要把所有红色的箭头填边对应连接出来,就可以得到一个强连通图。显然此图中我们只需添出度为0的点的个数,即5条边,就可以得到一个强连通图。
代码:
思路:先跑一遍Tarjan并进行缩点。缩完点后,得到一个DAG,设入度为0的点数位inCnt,出度为0的点数为outCnt,则答案为max(inCnt, outCnt)。注意如果跑完一遍图本身就是强连通的,则直接输出0。
下面证明为什么答案是max(inCnt, outCnt)。
先给出一个有向图。
假如这个是缩完点后的图,那我们如何添最少的变使它变成强连通图呢。
对于这个图,我们可以看到入度为0的点为: 1,2,6,7; 出度为0的点为 4,5,6,7,8。要使图变成强连通的,则显然要使:总的出度数 = 总的入度数,且保证每个点的出度和入度都大于0。那么我们可以先画下面这样的图:
红色箭头表示我们至少要添的有向边。
那么显然,我们只需要把“出”的箭头连到“入”的箭头上,且保证所有红色箭头都有得连接,那么就可以得到一个强连通图。所有“出”的箭头与“入”的箭头对应相连,即我们添的一条有向边是对应至少一条“入”箭头和至少一条“出”箭头,那么显然,添边的数量不会超过max{“入”的箭头数量,“出”的箭头的数量}。这一图中入度为0的点有4个,出度为0的有5个,所以至少添的有向边数为5。下图为其中一种添法。
只要把所有红色的箭头填边对应连接出来,就可以得到一个强连通图。显然此图中我们只需添出度为0的点的个数,即5条边,就可以得到一个强连通图。
代码:
#include <algorithm> #include <iostream> #include <sstream> #include <cstring> #include <cstdio> #include <vector> #include <string> #include <queue> #include <stack> #include <cmath> #include <set> #include <map> using namespace std; typedef long long LL; #define mem(a, n) memset(a, n, sizeof(a)) #define rep(i, n) for(int i = 0; i < (n); i ++) #define REP(i, t, n) for(int i = (t); i < (n); i ++) #define FOR(i, t, n) for(int i = (t); i <= (n); i ++) #define Min(a, b) a = min(a, b) #define ALL(v) v.begin(), v.end() #define si(a) scanf("%d", &a) #define sii(a, b) scanf("%d%d", &a, &b) #define siii(a, b, c) scanf("%d%d%d", &a, &b, &c) #define pb push_back #define eps 1e-8 const int inf = 0x3f3f3f3f, N = 2e4 + 5, M = 1e5 + 5, MOD = 1e9 + 7; int T, cas = 0; int n, m; int ne, dfsNum, top, tot; struct edge { int v, next; }e[M]; int head[M], dfn , low , vis , st , g , in , out ; void addEdge(int u, int v) { e[ne].v = v; e[ne].next = head[u]; head[u] = ne ++; } void init() { mem(dfn, 0), mem(low, 0), mem(vis, 0); mem(in, 0), mem(out, 0), mem(g, 0), mem(head, -1); dfsNum = ne = top = tot = 0; } void Tarjan(int u) { dfn[u] = low[u] = ++ dfsNum; st[top ++] = u; vis[u] = 1; for(int i = head[u]; i != -1; i = e[i].next) { int v = e[i].v; if(!dfn[v]) { Tarjan(v); Min(low[u], low[v]); } else if(vis[v]) Min(low[u], dfn[v]); } if(low[u] == dfn[u]) { tot ++; while(1) { int k = st[-- top]; g[k] = tot; vis[k] = 0; if(k == u) break; } } } void work() { for(int u = 1; u <= n; u ++) { for(int i = head[u]; i != -1; i = e[i].next) { int v = e[i].v; if(g[u] == g[v]) continue; out[g[u]] ++; in[g[v]] ++; } } } void gao() { work(); int ans1 = 0, ans2 = 0, ans; for(int i = 1; i <= tot; i ++) { if(in[i] == 0) ans1 ++; if(out[i] == 0) ans2 ++; } ans = max(ans1, ans2); if(tot == 1) ans = 0; printf("%d\n", ans); } int main(){ #ifdef LOCAL freopen("/Users/apple/input.txt", "r", stdin); // freopen("/Users/apple/out.txt", "w", stdout); #endif si(T); while(T --) { init(); sii(n, m); int u, v; for(int i = 0; i < m; i ++) { sii(u, v); addEdge(u, v); } for(int u = 1; u <= n; u ++) if(!dfn[u]) Tarjan(u); gao(); } return 0; }
相关文章推荐
- EasyUI常用控件的禁用方法
- request biji
- leetcode笔记:N-Queens II
- Druid监控数据库
- duilib 入门一之界面库基本原理
- 如何解决virtualbox中不能打开一个虚拟任务之uuid不匹配的问题
- 移植opencv到pcDuino
- arduino ide找不到目标文件
- HDU-5568 sequence2(DP+高精度)
- HDU5568/BestCoder Round #63 (div.2) B.sequence2 dp+高精度
- HDU5567/BestCoder Round #63 (div.2) A sequence1 水
- hdoj5567sequence1
- UILabel,UITextField,UIButton三大基础控件总结
- BestCoder Round #63 (div.1) A.sequence2
- UItableView
- UESTC 1217 The Battle of Chibi (树状数组 + 离散化 + 动态规划)
- sequence1(暴力)
- hdoj sequence1 5567 (简单暴力)
- HDOJ 5567 sequence1
- HDU 5567 sequence1(暴力)——BestCoder Round #63(div.2)