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

连通分量___刷题记录

时间:2015-07-30 10:55:57      阅读:112      评论:0      收藏:0      [点我收藏+]

标签:

hdu 1269

判断是否存在一个强连通

技术分享
 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<algorithm>
 5 #include<stack>
 6 #include<vector>
 7 using namespace std;
 8 
 9 const int maxn = 10005;
10 vector<int> g[maxn];
11 stack<int> S;
12 
13 int n,m;
14 int sccno[maxn],low[maxn],pre[maxn];
15 int scc_cnt,dfs_clock;
16 
17 void init(){
18     while(!S.empty()) S.pop();
19     for(int i = 1;i <= n;i++) g[i].clear();
20     scc_cnt = dfs_clock = 0;
21     memset(sccno,0,sizeof(sccno));
22     memset(low,0,sizeof(low));
23     memset(pre,0,sizeof(pre));
24 }
25 
26 void dfs(int u){
27     low[u] = pre[u] = ++dfs_clock;
28     S.push(u);
29     for(int i = 0;i < g[u].size();i++){
30         int v = g[u][i];
31         if(!pre[v]){
32             dfs(v);
33             low[u] = min(low[v],low[u]);
34         }
35         else if(!sccno[v]) low[u] = min(low[u],pre[v]);
36     }
37     if(low[u] == pre[u]){
38         scc_cnt++;
39         for(;;){
40             int x = S.top();S.pop();
41             sccno[x] = scc_cnt;
42             if(x == u) break;
43         }
44     }
45 }
46 
47 void find_scc(){
48     for(int i = 1;i <= n;i++){
49         if(!pre[i]) dfs(i);
50     }
51     if(scc_cnt == 1) printf("Yes\n");
52     else printf("No\n");
53 }
54 
55 int main(){
56     while(scanf("%d %d",&n,&m) != EOF && (n ||m)){
57         init();
58         for(int i = 0;i < m;i++){
59             int u,v;
60             scanf("%d %d",&u,&v);
61             g[u].push_back(v);
62         }
63         find_scc();
64     }
65     return 0;
66 }
View Code

la 4287

白书上的例题

给一张图,问最少需要添加多少条边变成强连通

先求一遍强连通,然后把每一个强连通分量缩成一个点,再扫一遍边,如果发现一条边的两端u,v属于不同的强连通分量,如果是u--->v,那么in[scc[v]]++,out[scc[u]++;

最后统计入度为0的强连通分量个数a,出度为0的b,max(a,b)即为添加的最少边数

 

因为对于一个强连通,每一个点的入度至少为1.出度也至少为1,添加max(a,b)条边,能够满足这个条件

 

----不知道为什么用vector存图写的wa了,换成邻接表就过了

技术分享
  1 #include<cstdio>
  2 #include<cstring>
  3 #include<iostream>
  4 #include<algorithm>
  5 #include<stack>
  6 using namespace std;
  7 
  8 const int maxn = 20005;
  9 int first[maxn];
 10 int low[maxn],pre[maxn],sc[maxn];
 11 int din[maxn],dout[maxn];
 12 int n,m;
 13 int ecnt,scnt,dfs_clock;
 14 stack<int> S;
 15 
 16 struct Edge{
 17     int v,next;
 18 }e[3*maxn];
 19 
 20 void init(){
 21     ecnt = 0;
 22     memset(first,-1,sizeof(first));
 23     memset(din,0,sizeof(din));
 24     memset(dout,0,sizeof(dout));
 25 }
 26 
 27 void addedges(int u,int v){
 28     e[ecnt].v = v;
 29     e[ecnt].next = first[u];
 30     first[u] = ecnt++;
 31 }
 32 
 33 void dfs(int u){
 34     low[u] = pre[u] = ++dfs_clock;
 35     S.push(u);
 36     for(int i = first[u];~i;i = e[i].next){
 37         int v = e[i].v;
 38         if(!pre[v]){
 39             dfs(v);
 40             low[u] = min(low[u],low[v]);
 41         }
 42         else if(!sc[v]) low[u] = min(low[u],pre[v]);
 43     }
 44     if(pre[u] == low[u]){
 45         scnt++;
 46         for(;;){
 47             int x = S.top();S.pop();
 48             sc[x] = scnt;
 49             if(x == u) break;
 50         }
 51     }
 52 }
 53 
 54 void find_scc(){
 55     while(!S.empty()) S.pop();
 56     memset(low,0,sizeof(low));memset(pre,0,sizeof(pre));
 57     memset(sc,0,sizeof(sc));
 58     dfs_clock = scnt = 0;
 59     for(int i = 1;i <= n;i++) if(!pre[i]) dfs(i);
 60 }
 61 
 62 int main(){
 63     int T;
 64     scanf("%d",&T);
 65     while(T--){
 66         scanf("%d %d",&n,&m);
 67         init();
 68         for(int i = 1;i <= m;i++){
 69             int u,v;
 70             scanf("%d %d",&u,&v);
 71             addedges(u,v);
 72         }
 73         find_scc();
 74         if(scnt == 1){
 75             printf("0\n");
 76             continue;
 77         }
 78         for(int u = 1;u <= n;u++){
 79             for(int i = first[u];~i;i = e[i].next){
 80                 int v = e[i].v;
 81                 if(sc[u] != sc[v]){
 82                     din[sc[v]]++;
 83                     dout[sc[u]]++;
 84                 }
 85             }
 86         }
 87         
 88     //    printf("scnt = %d\n",scnt);
 89     //    for(int i = 1;i <= scnt;i++)
 90     //    printf("din[%d] = %d  dout[%d] = %d\n",i,din[i],i,dout[i]);
 91         
 92         int a = 0,b = 0;
 93         for(int i = 1;i <= scnt;i++){
 94             if(din[i] == 0) a++;
 95             if(dout[i] == 0) b++;
 96         }
 97         printf("%d\n",max(a,b));
 98     }
 99     return 0;
100 }
View Code

 

连通分量___刷题记录

标签:

原文地址:http://www.cnblogs.com/wuyuewoniu/p/4688309.html

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