loj 1168(Tarjan应用)

来源:互联网 发布:兔子白网络 编辑:程序博客网 时间:2024/05/22 07:57

题目链接: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         }else128             puts("NO");129     }130     return 0;131 }
View Code

 

0 0