loj 1168(Tarjan应用)

题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=26882

思路:一开始把题意理解错了,还以为是简单路径,然后仔细一看发现是一条路径,意思就是说从起点出发,把所有的点走一遍,于是就要考虑强连通分量,因为对于同一个强连通分量的点是相互可达的,于是我们可以先缩点,建新图,统计新图中顶点的入度与出度的关系,判断即可。

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<cstdlib>
  5 #include<cmath>
  6 #include<climits>
  7 #include<algorithm>
  8 #include<stack>
  9 #include<map>
 10 #include<set>
 11 #include<vector>
 12 #include<queue>
 13 #include<list>
 14 using namespace std;
 15 #define MAXN 1111
 16 #define inf 1<<30
 17 #define INF 1LL<<60
 18 #define FILL(a,b) memset(a,b,sizeof(a))
 19 typedef long long ll;
 20 typedef unsigned long long llu;
 21 typedef pair<int,int>PP;
 22 template<class T> inline T Get_MIN(const T &a,const T &b){ return a < b ? a : b; }
 23 template<class T> inline T Get_MAX(const T &a,const T &b){ return a > b ? a : b; }
 24 template<class T> inline T ABS(const T &a){ return a < 0 ? -a : a; }
 25 
 26 int n,m,k;
 27 bool vis[MAXN];
 28 vector<vector<int> >g,num;
 29 map<int,int>ID;
 30 
 31 int low[MAXN],dfn[MAXN],color[MAXN];
 32 int scc_count,cnt;
 33 bool mark[MAXN];
 34 stack<int>S;
 35 
 36 void Tarjan(int u)
 37 {
 38     low[u]=dfn[u]=++cnt;
 39     mark[u]=true;
 40     S.push(u);
 41     for(int i=0;i<g[u].size();i++){
 42         int v=g[u][i];
 43         if(dfn[v]==0){
 44             Tarjan(v);
 45             low[u]=Get_MIN(low[u],low[v]);
 46         }else if(mark[v]){
 47             low[u]=Get_MIN(low[u],dfn[v]);
 48         }
 49     }
 50     if(low[u]==dfn[u]){
 51         scc_count++;
 52         int v;
 53         do{
 54             v=S.top();
 55             S.pop();
 56             mark[v]=false;
 57             color[v]=scc_count;
 58         }while(u!=v);
 59     }
 60 }
 61 
 62 int In_degree[MAXN],Out_degree[MAXN];
 63 void Build()
 64 {
 65     FILL(In_degree,0);
 66     FILL(Out_degree,0);
 67     for(int u=1;u<=m;u++){
 68         for(int i=0;i<g[u].size();i++){
 69             int v=g[u][i];
 70             if(color[u]!=color[v]){
 71                 In_degree[color[v]]++;
 72                 Out_degree[color[u]]++;
 73             }
 74         }
 75     }
 76 }
 77 
 78 
 79 
 80 int main()
 81 {
 82     int _case,u,v,t=1;
 83     scanf("%d",&_case);
 84     while(_case--){
 85         scanf("%d",&n);
 86         g.clear();
 87         g.resize(1010);
 88         num.clear();
 89         num.resize(1010);
 90         ID.clear();
 91         FILL(vis,false);
 92         m=0;
 93         for(int i=1;i<=n;i++){
 94             scanf("%d",&k);
 95             while(k--){
 96                 scanf("%d%d",&u,&v);
 97                 if(!vis[u])vis[u]=true,ID[u]=++m;
 98                 if(!vis[v])vis[v]=true,ID[v]=++m;
 99                 g[ID[u]].push_back(ID[v]);
100             }
101         }
102         FILL(dfn,0);
103         FILL(mark,false);
104         scc_count=cnt=0;
105         for(int i=1;i<=m;i++){
106             if(dfn[i]==0)Tarjan(i);
107         }
108         printf("Case %d: ",t++);
109         if(scc_count==1){
110             puts("YES");
111             continue;
112         }
113         Build();
114         if(Out_degree[color[ID[0]]]==0||In_degree[color[ID[0]]]!=0){
115             puts("NO");
116             continue;
117         }
118         int cnt1,cnt2,cnt3;
119         cnt1=cnt2=cnt3=0;
120         for(int i=1;i<=scc_count;i++){
121             if(In_degree[i]==0&&Out_degree[i]==1)cnt1++;
122             else if(In_degree[i]==1&&Out_degree[i]==0)cnt2++;
123             else if(In_degree[i]==1&&Out_degree[i]==1)cnt3++;
124         }
125         if(cnt1==1&&cnt2==1&&cnt1+cnt2+cnt3==scc_count){
126             puts("YES");
127         }else
128             puts("NO");
129     }
130     return 0;
131 }
View Code

 

posted @ 2013-10-03 17:00  ihge2k  阅读(235)  评论(0编辑  收藏  举报