先用Tarjan求出强连通分量,其他算法也可以的,再缩点,然后从入度为0的点开始暴搜,如果深度达到强连通分量的个数即可行。这一题一定要注意一点:我用cin的时候TLE,该scanf就好了。。。
View Code
1 #include <cstdio> 2 #include <cstring> 3 #include <vector> 4 using namespace std; 5 6 const int maxN = 1000 + 10; 7 vector<int> edge[maxN]; 8 int low[maxN]; 9 int stack[maxN],top; 10 int del[maxN]; 11 int DFN[maxN]; 12 int ComNum; 13 int cnt; 14 15 bool flag; 16 bool in[maxN]; 17 vector<int> sedge[maxN]; 18 19 void Tarjan(int x) 20 { 21 stack[top ++] = x; 22 low[x] = DFN[x] = cnt ++; 23 24 int len = edge[x].size(); 25 for(int i = 0;i < len;i ++) 26 { 27 int u = edge[x][i]; 28 if(!DFN[u]) 29 { 30 Tarjan(u); 31 if(low[x] > low[u]) low[x] = low[u]; 32 } 33 else if(!del[u]) 34 { 35 if(low[x] > DFN[u]) low[x] = DFN[u]; 36 } 37 } 38 39 if(DFN[x] == low[x]) 40 { 41 ComNum ++; 42 do 43 { 44 del[stack[top-1]] = ComNum; 45 }while(stack[--top] != x); 46 } 47 } 48 49 void UseTarjan(int n) 50 { 51 memset(DFN,0,sizeof(DFN)); 52 memset(del,0,sizeof(del)); 53 ComNum = 0; 54 top = 0; 55 cnt = 1; 56 for(int i = 1;i <= n;i ++) 57 { 58 if(!DFN[i]) 59 { 60 Tarjan(i); 61 } 62 } 63 } 64 65 void dfs(int k,int cc) 66 { 67 in[k] = true; 68 //cc ++; 69 if(cc == ComNum) 70 { 71 flag = true; 72 return; 73 } 74 int len = sedge[k].size(); 75 for(int i = 0;i < len;i ++) 76 { 77 if(!in[sedge[k][i]]) 78 { 79 dfs(sedge[k][i],cc+1); 80 } 81 if(flag) 82 return; 83 } 84 } 85 86 int main() 87 { 88 int n,m; 89 int cases; 90 scanf("%d",&cases); 91 while(cases --) 92 { 93 scanf("%d%d",&n,&m); 94 for(int i = 0;i <= n;i ++) 95 { 96 edge[i].clear(); 97 sedge[i].clear(); 98 } 99 100 for(int i = 0;i < m;i ++) 101 { 102 int u,v; 103 scanf("%d%d",&u,&v); 104 edge[u].push_back(v); 105 } 106 UseTarjan(n); 107 if(ComNum == 1) 108 { 109 printf("Yes\n"); 110 continue; 111 } 112 int i = 1; 113 memset(in,false,sizeof(in)); 114 for(;i <= n;i ++) 115 { 116 int len = edge[i].size(); 117 for(int j = 0;j < len;j ++) 118 { 119 if(del[i] != del[edge[i][j]]) 120 { 121 in[del[edge[i][j]]] = true; 122 sedge[del[i]].push_back(del[edge[i][j]]);//将缩点构成图 123 } 124 } 125 } 126 int t = 0; 127 int k = 0; 128 for(i = 1;i <= ComNum;i ++) 129 { 130 if(!in[i])//寻找入度为0的点 131 { 132 t ++; 133 k = i;//记录下入度为0的点 134 } 135 } 136 if(t > 1)//如果入度为0的点超过一个这几个点无法到达 137 { 138 printf("No\n"); 139 continue; 140 } 141 142 flag = false; 143 memset(in,false,sizeof(in)); 144 dfs(k,1);//从入度为0的点开始搜 145 if(flag) 146 { 147 printf("Yes\n"); 148 } 149 else 150 { 151 printf("No\n"); 152 } 153 } 154 155 return 0; 156 }