LA 4287 等价性证明(强连通分量缩点)
Posted 谦谦君子,陌上其华
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LA 4287 等价性证明(强连通分量缩点)相关的知识,希望对你有一定的参考价值。
https://vjudge.net/problem/UVALive-4287
题意:
给出n个结点m条边的有向图,要求加尽量少的边,使得新图强连通。
思路:
强连通分量缩点,然后统计缩点后的图的每个结点是否还需要出度和入度。
1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 #include<cstdio> 5 #include<sstream> 6 #include<vector> 7 #include<stack> 8 #include<queue> 9 #include<cmath> 10 #include<map> 11 #include<set> 12 using namespace std; 13 typedef long long ll; 14 typedef pair<int,ll> pll; 15 const int INF = 0x3f3f3f3f; 16 const int maxn=20000+5; 17 18 int n, m; 19 int tot; 20 int dfs_clock; 21 int scc_cnt; 22 int in[maxn]; 23 int out[maxn]; 24 int pre[maxn]; 25 int head[maxn]; 26 int sccno[maxn]; 27 int lowlink[maxn]; 28 29 stack<int> S; 30 31 struct node 32 { 33 int v; 34 int next; 35 }e[50000+5]; 36 37 void addEdge(int u, int v) 38 { 39 e[tot].v=v; 40 e[tot].next=head[u]; 41 head[u]=tot++; 42 } 43 44 void dfs(int u) 45 { 46 pre[u]=lowlink[u]=++dfs_clock; 47 S.push(u); 48 for(int i=head[u];i!=-1;i=e[i].next) 49 { 50 int v=e[i].v; 51 if(!pre[v]) 52 { 53 dfs(v); 54 lowlink[u]=min(lowlink[u],lowlink[v]); 55 } 56 else if(!sccno[v]) 57 { 58 lowlink[u]=min(lowlink[u],pre[v]); 59 } 60 } 61 62 if(lowlink[u]==pre[u]) 63 { 64 scc_cnt++; 65 for(;;) 66 { 67 int x=S.top();S.pop(); 68 sccno[x]=scc_cnt; 69 if(x==u) break; 70 } 71 } 72 } 73 74 75 void find_scc() 76 { 77 dfs_clock=scc_cnt=0; 78 memset(sccno,0,sizeof(sccno)); 79 memset(pre,0,sizeof(pre)); 80 for(int i=1;i<=n;i++) 81 { 82 if(!pre[i]) dfs(i); 83 } 84 } 85 86 int main() 87 { 88 //freopen("in.txt","r",stdin); 89 int T; 90 scanf("%d",&T); 91 while(T--) 92 { 93 scanf("%d%d",&n,&m); 94 tot=0; 95 memset(head,-1,sizeof(head)); 96 while(m--) 97 { 98 int u,v; 99 scanf("%d%d",&u,&v); 100 addEdge(u,v); 101 } 102 find_scc(); 103 for(int i=1;i<=scc_cnt;i++) in[i]=out[i]=1; 104 for(int u=1;u<=n;u++) 105 { 106 for(int i=head[u];i!=-1;i=e[i].next) 107 { 108 int v=e[i].v; 109 if(sccno[u]!=sccno[v]) in[sccno[v]]=out[sccno[u]]=0; //u,v是桥,所以v不需要入度,u不需要出度 110 } 111 } 112 113 114 int a=0,b=0; 115 for(int i=1;i<=scc_cnt;i++) 116 { 117 if(in[i]) a++; 118 if(out[i]) b++; 119 } 120 int ans=max(a,b); 121 if(scc_cnt==1) ans=0; 122 printf("%d\n",ans); 123 } 124 return 0; 125 }
以上是关于LA 4287 等价性证明(强连通分量缩点)的主要内容,如果未能解决你的问题,请参考以下文章
UVALIVE 4287 Proving Equivalences (强连通分量+缩点)
POJ 2186 - Popular Cows - 强连通分量,缩点