码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2015-03-12 19:01:55      阅读:162      评论:0      收藏:0      [点我收藏+]

标签:

大意:

告诉你有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

 

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

标签:

原文地址:http://www.cnblogs.com/zhanzhao/p/4333091.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!