题目链接: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 }