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 }
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 }
时间: 2024-10-02 14:20:25