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 }