hDU2767Equivalences【强连通缩点+添加多少条边可以使有向图强连通】

来源:互联网 发布:linux 系统日志 命令 编辑:程序博客网 时间:2024/05/17 07:56

大意:

告诉你有n个点  m条单向边  问最少添加多少条边能将该图变成强连通

分析:

先用强连通进行缩点  缩成一个有向无环图 

然后我们考虑如何才能使 这个有向无环图变成一个强连通

我的第一反应是求最小路径覆盖  然后再首尾相连  结果时间复杂度承受不住

其实想到这里可以大胆猜想一下了   

刚刚提到了  首尾连接这个思想

我们只要统计有多少个头多少个尾  然后用尾去连接头就好了  答案就是首尾最大值
统计首尾也就是统计入度出度为0的点的个数

 

需要注意的是  若强连通缩点之后点缩成了一个  那么这个点本身就是一个强连通

 

代码:

  1 #include <iostream>  2 #include <cstdio>  3 #include <cstring>  4 #include <map>  5 #define clr(x) memset(x, 0, sizeof(x))  6 using namespace std;  7 int min(int a, int b) {  8     return a > b ? b : a;  9 } 10  11 const int maxn = 500005; 12 const int maxm = 500005; 13  14 struct Edge { 15     int to, next; 16 }e[maxm]; 17 int tot; 18 int head[maxn]; 19 int id[maxn]; 20  21 void add(int u, int v) { 22     e[tot].to = v; 23     e[tot].next = head[u]; 24     head[u] = tot++; 25 } 26 int n, m; 27  28 int s[maxn]; 29 int ins[maxn]; 30 int s_cnt; 31 int id_cnt; 32 int cnt; 33 int dfn[maxn], low[maxn]; 34 void dfs(int u) { 35     s[s_cnt++] = u; 36     ins[u] = 1; 37     dfn[u] = low[u] = cnt++; 38     for(int i = head[u]; i; i = e[i].next) { 39         int v = e[i].to; 40         if(!dfn[v]) { 41             dfs(v); 42             low[u] = min(low[u], low[v]); 43         } else if(ins[v]) { 44             low[u] = min(low[u], dfn[v]); 45         } 46     } 47     if(dfn[u] == low[u]) { 48         int x; 49         id_cnt++; 50         do { 51             x = s[--s_cnt]; 52             ins[x] = 0; 53             id[x] = id_cnt; 54         } while(x != u); 55     } 56 } 57  58 void init() { 59     clr(head); 60     clr(dfn); 61     clr(low); 62     clr(id); 63     clr(ins); 64     cnt = 1; 65     s_cnt = 1; 66     id_cnt = 0; 67     tot = 1; 68 } 69 int ind[maxn], outd[maxn]; 70  71 int main() { 72     int t; 73     scanf("%d",&t); 74     int u, v; 75     while(t--) { 76         scanf("%d %d",&n, &m); 77         init(); 78         for(int i = 1; i <= m; i++) { 79             scanf("%d %d",&u, &v); 80             add(u, v); 81         } 82         for(int i = 1; i <= n; i++) { 83             if(!dfn[i]) { 84                 dfs(i); 85             } 86         } 87         if(id_cnt == 1) { 88             printf("%d\n", 0); 89             continue; 90         } 91         int ans1 = 0; int ans2 = 0; 92         clr(ind); clr(outd); 93         for(int i = 1; i <= n; i++) { 94             for(int j = head[i]; j; j = e[j].next) { 95                 int x = e[j].to; 96                 if(id[i] != id[x]) { 97                     ind[id[x]]++; 98                     outd[id[i]]++; 99                 }100             }101         }102         for(int i = 1; i <= id_cnt; i++) {103             if(ind[i] == 0) ans1++;104             if(outd[i] == 0) ans2++;105         } 106         if(ans1 < ans2) ans1 = ans2;107         printf("%d\n", ans1);108     }109     return 0;110 }111 112     
View Code

 

0 0
原创粉丝点击