Time Limit: 2000MS | Memory Limit: 65536K | |
Total Submissions: 21685 | Accepted: 8852 |
Descriptionios
Inputide
Outputthis
Sample Inputspa
3 3 1 2 2 1 2 3
Sample Outputcode
1
Hintorm
Sourceblog
初学强连通份量第一题排序
假设有两头牛A和B都被其余全部牛认为是红人,那么显然A、B也互相认为是红人,即存在一个包含A、B两个顶点的圈,即A和B同属于同一个强连通份量。由此咱们可知,若是一头牛被其它全部牛认为是红人,那么它所在的强连通份量内的全部牛都被其余全部牛认为是红人。这样咱们把图进行强连通分解后,至多有一个强连通份量知足题目的条件。ip
咱们知道,把一个图进行强连通份量分解后,能够获得各个强连通份量拓扑排序后的顺序,而在此题中,惟一可能成为解的只有拓扑序最后的一个强连通份量。所以咱们在对图进行强连通份量分解后,只要检查最后一个强连通份量中的一个顶点是否从全部顶点到达就行了。ci
1 #include<iostream> 2 #include<cstdio> 3 #include<vector> 4 #include<cstring> 5 #define MAX_V 10050 6 7 using namespace std; 8 9 int V,E; 10 vector<int> G[MAX_V]; 11 vector<int> rG[MAX_V]; 12 vector<int> vs; 13 bool used[MAX_V]; 14 int cmp[MAX_V]; 15 16 void add_edge(int _from,int _to) 17 { 18 G[_from].push_back(_to); 19 rG[_to].push_back(_from); 20 } 21 22 void dfs(int v) 23 { 24 used[v]=true; 25 for(int i=0;i<G[v].size();i++) 26 if(!used[G[v][i]]) 27 dfs(G[v][i]); 28 vs.push_back(v); 29 } 30 31 void rdfs(int v,int k) 32 { 33 used[v]=true; 34 cmp[v]=k; 35 for(int i=0;i<rG[v].size();i++) 36 if(!used[rG[v][i]]) 37 rdfs(rG[v][i],k); 38 } 39 40 int scc() 41 { 42 memset(used,false,sizeof(used)); 43 vs.clear(); 44 for(int v=0;v<V;v++) 45 if(!used[v]) 46 dfs(v); 47 48 memset(used,false,sizeof(used)); 49 int k=0; 50 for(int i=vs.size()-1;i>=0;i--) 51 if(!used[vs[i]]) 52 { 53 rdfs(vs[i],k); 54 k++; 55 } 56 57 return k; 58 } 59 60 int main() 61 { 62 while(scanf("%d %d",&V,&E)==2) 63 { 64 for(int i=0;i<V;i++) 65 { 66 G[i].clear(); 67 rG[i].clear(); 68 } 69 70 int a,b; 71 for(int i=1;i<=E;i++) 72 { 73 scanf("%d %d",&a,&b); 74 add_edge(a-1,b-1); 75 } 76 77 int k=scc()-1; 78 int u,ans=0; 79 80 for(int i=0;i<V;i++) 81 if(cmp[i]==k) 82 { 83 u=i; 84 ans++; 85 } 86 87 //再反向图上再进行一次DFS,判断最后一个强连通份量中的点是不是从全部点均可达的 88 memset(used,false,sizeof(used)); 89 if(ans) 90 { 91 rdfs(u,0); 92 for(int i=0;i<V;i++) 93 if(!used[i]) 94 { 95 ans=0; 96 break; 97 } 98 } 99 100 printf("%d\n",ans); 101 } 102 103 return 0; 104 }