题意:
判断所给的有向图是否是一个强连通图。
思路:
如果连通分量大于1则必定No,如果强连通分量大于1也是No。tarjan算法求强连通分量。
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <vector> 5 #include <unordered_map> 6 #include <stack> 7 #include <iostream> 8 #include <bits/stdc++.h> 9 #define LL long long 10 #define pii pair<int,int> 11 using namespace std; 12 const int N=10000+5; 13 const int INF=0x7f7f7f7f; 14 vector<int> vect[N]; 15 stack<int> stac; 16 int n, m; 17 18 int lowlink[N], dfn[N], scc_no[N]; 19 int dfn_clock, scc_cnt; 20 21 void DFS(int x) 22 { 23 stac.push(x); 24 lowlink[x]=dfn[x]=++dfn_clock; 25 for(int i=0; i<vect[x].size(); i++) 26 { 27 int t=vect[x][i]; 28 if(!dfn[t]) 29 { 30 DFS(t); 31 lowlink[x]=min(lowlink[x],lowlink[t]); 32 } 33 else if(!scc_no[t]) 34 lowlink[x]=min(lowlink[x],dfn[t]); 35 } 36 if(lowlink[x]==dfn[x]) 37 { 38 scc_cnt++; 39 while(true) 40 { 41 int t=stac.top(); 42 stac.pop(); 43 scc_no[t]=scc_cnt; 44 if(x==t) break; 45 } 46 } 47 48 } 49 50 51 bool cal() 52 { 53 memset(lowlink, 0, sizeof(lowlink)); 54 memset(dfn, 0, sizeof(dfn)); 55 memset(scc_no, 0, sizeof(scc_no)); 56 57 scc_cnt=dfn_clock=0; 58 DFS(1); 59 if(scc_cnt>1) return false; //多个强连通分量 60 for(int i=1; i<=n; i++) if(!scc_no[i]) return false; //多个连通分量 61 return true; 62 } 63 64 65 int main() 66 { 67 freopen("input.txt", "r", stdin); 68 int a, b; 69 while(scanf("%d%d",&n,&m), n+m) 70 { 71 for(int i=1; i<=n; i++) vect[i].clear(); 72 for(int i=0; i<m; i++) 73 { 74 scanf("%d%d",&a,&b); 75 vect[a].push_back(b); 76 } 77 if(cal()) puts("Yes"); 78 else puts("No"); 79 } 80 return 0; 81 }