HDU 3594 Cactus(仙人掌问题)
Posted 谦谦君子,陌上其华
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU 3594 Cactus(仙人掌问题)相关的知识,希望对你有一定的参考价值。
http://acm.hdu.edu.cn/showproblem.php?pid=3594
题意:
一个有向图,判断是否强连通和每条边只在一个环中。
思路:
仙人掌问题。
用Tarjan算法判断强连通分量的时候,记录每节结点的父节点。当找到一个环后,回溯将该环上的所有结点+1,如果有结点出现2次了,则说明不是仙人掌了。
1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 #include<cstdio> 5 #include<vector> 6 #include<queue> 7 #include<cmath> 8 #include<map> 9 #include<stack> 10 using namespace std; 11 12 const int maxn=20000+5; 13 14 int n,m; 15 16 vector<int> G[maxn]; 17 int in[maxn]; 18 int pre[maxn],lowlink[maxn],sccno[maxn],dfs_clock,scc_cnt; 19 int fa[maxn]; 20 21 22 int find(int u,int v) 23 { 24 while(fa[u]!=v) 25 { 26 in[u]++; 27 if(in[u]>1) return 0; 28 u=fa[u]; 29 } 30 return 1; 31 } 32 33 int dfs(int u) 34 { 35 pre[u]=lowlink[u]=++dfs_clock; 36 for(int i=0;i<G[u].size();i++) 37 { 38 int v=G[u][i]; 39 if(!pre[v]) 40 { 41 fa[v]=u; 42 if(!dfs(v)) return 0; 43 lowlink[u]=min(lowlink[u],lowlink[v]); 44 } 45 else if(!sccno[v]) 46 { 47 lowlink[u]=min(lowlink[u],pre[v]); 48 if(!find(u,v)) return 0; 49 } 50 } 51 if(lowlink[u]==pre[u]) 52 { 53 scc_cnt++; 54 if(scc_cnt>1) return 0; 55 } 56 return 1; 57 } 58 59 int find_scc() 60 { 61 dfs_clock=scc_cnt=0; 62 memset(sccno,0,sizeof(sccno)); 63 memset(pre,0,sizeof(pre)); 64 memset(in,0,sizeof(in)); 65 memset(fa,0,sizeof(fa)); 66 for(int i=0;i<n;i++) 67 if(!pre[i]) if(!dfs(i)) return 0; 68 return 1; 69 } 70 71 int main() 72 { 73 //freopen("D:\\input.txt","r",stdin); 74 int T; 75 scanf("%d",&T); 76 while(T--) 77 { 78 scanf("%d",&n); 79 for(int i=0;i<n;i++) G[i].clear(); 80 while(true) 81 { 82 int u,v; 83 scanf("%d%d",&u,&v); 84 if(u==0 && v==0) break; 85 G[u].push_back(v); 86 } 87 if(find_scc() && scc_cnt==1) cout<<"YES"<<endl; 88 else cout<<"NO"<<endl; 89 } 90 return 0; 91 }
以上是关于HDU 3594 Cactus(仙人掌问题)的主要内容,如果未能解决你的问题,请参考以下文章
bzoj1023 [SHOI2008]cactus仙人掌图 & poj3567 Cactus Reloaded——求仙人掌直径
bzoj1023: [SHOI2008]cactus仙人掌图
bzoj 1023 [SHOI2008]cactus仙人掌图 ( poj 3567 Cactus Reloaded )——仙人掌直径模板