2014-10-14 21:44:18
思路:问一个图是否是单连通的。先对全图求一次SCC,可以知道每个SCC内的点都是单连通的,那么把每个SCC缩点构建出DAG之后再判断这个DAG是否单连通即可,方法是DAG动规找出最长链,如果最长链上的点个数等于SCC个数,那么DAG单连通。(因为如果最长链都不能覆盖所有点,那么必定有两个点之间是无法到达的)
1 /************************************************************************* 2 > File Name: 2762.cpp 3 > Author: Nature 4 > Mail: 564374850@qq.com 5 > Created Time: Tue 14 Oct 2014 07:42:48 PM CST 6 ************************************************************************/ 7 8 #include <cstdio> 9 #include <cstring> 10 #include <cstdlib> 11 #include <cmath> 12 #include <vector> 13 #include <map> 14 #include <set> 15 #include <stack> 16 #include <queue> 17 #include <iostream> 18 #include <algorithm> 19 using namespace std; 20 #define lp (p << 1) 21 #define rp (p << 1|1) 22 #define getmid(l,r) (l + (r - l) / 2) 23 #define MP(a,b) make_pair(a,b) 24 typedef long long ll; 25 const int INF = 1 << 30; 26 const int maxn = 1010; 27 28 int T,n,m; 29 int first[maxn],next[maxn * 6],ver[maxn * 6],ecnt; 30 int low[maxn],dfn[maxn],sc[maxn],scnt,tot; 31 int f1[maxn],n1[maxn * 6],v1[maxn * 6],e1; 32 int dp[maxn]; 33 stack<int> S; 34 35 void Add_edge(int u,int v){ 36 next[++ecnt] = first[u]; 37 ver[ecnt] = v; 38 first[u] = ecnt; 39 } 40 41 void Init(){ 42 memset(first,-1,sizeof(first)); 43 memset(f1,-1,sizeof(f1)); 44 memset(dp,0,sizeof(dp)); 45 tot = ecnt = scnt = 0; 46 e1 = 0; 47 } 48 49 void Dfs(int p){ 50 dfn[p] = low[p] = ++tot; 51 S.push(p); 52 for(int i = first[p]; i != -1; i = next[i]){ 53 int v = ver[i]; 54 if(!dfn[v]){ 55 Dfs(v); 56 low[p] = min(low[p],low[v]); 57 } 58 else if(!sc[v]){ 59 low[p] = min(low[p],dfn[v]); 60 } 61 } 62 if(low[p] == dfn[p]){ 63 ++scnt; 64 while(1){ 65 int x = S.top(); 66 S.pop(); 67 sc[x] = scnt; 68 if(x == p) break; 69 } 70 } 71 } 72 73 void Tarjan(){ 74 memset(dfn,0,sizeof(dfn)); 75 memset(low,0,sizeof(low)); 76 memset(sc,0,sizeof(sc)); 77 while(!S.empty()) S.pop(); 78 for(int i = 1; i <= n; ++i) 79 if(!dfn[i]) Dfs(i); 80 } 81 82 void Add_edge1(int u,int v){ 83 n1[++e1] = f1[u]; 84 v1[e1] = v; 85 f1[u] = e1; 86 } 87 88 int Solve(int p){ 89 if(p == 0) return 0; 90 if(dp[p]) return dp[p]; 91 for(int i = f1[p]; i != -1; i = n1[i]){ 92 int v = v1[i]; 93 dp[p] = max(dp[p],Solve(v)); 94 } 95 return dp[p] = dp[p] + 1; 96 } 97 98 int main(){ 99 int a,b; 100 scanf("%d",&T); 101 while(T--){ 102 Init(); 103 scanf("%d%d",&n,&m); 104 for(int i = 1; i <= m; ++i){ 105 scanf("%d%d",&a,&b); 106 Add_edge(a,b); 107 } 108 Tarjan(); 109 for(int k = 1; k <= n; ++k){ 110 for(int i = first[k]; i != -1; i = next[i]){ 111 int v = ver[i]; 112 if(sc[k] != sc[v]){ 113 Add_edge1(sc[k],sc[v]); 114 } 115 } 116 } 117 int ans = 0; 118 for(int i = 1; i <= scnt && ans < scnt; ++i) 119 ans = max(ans,Solve(i)); 120 if(ans >= scnt) printf("Yes\n"); 121 else printf("No\n"); 122 } 123 return 0; 124 }