Shirlies
宁静专注认真的程序媛~

先用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 }
posted on 2012-09-09 21:05  Shirlies  阅读(163)  评论(0编辑  收藏  举报