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

 

你可能感兴趣的:(tar)