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 }
时间: 2024-08-10 00:07:31

HDU 3594 Cactus(仙人掌问题)的相关文章

HDU - 3594 Cactus(仙人掌图)

题目大意:给出仙人掌图的定义: 1.必须是强连通 2.每条边只能属于一个环 解题思路:在tarjan算法中加入点东西就可以判断了 只要该点能连到之前的点,那么形成环了,找到这个环的所有的边,并标记 如果有一条边被标记了两次了,那图就不是仙人掌图了 关键是怎么找到这个环的所有边,我们可以引入另一个栈,这个栈存放的是边的序号 假设当前点为u,u点连回之前的点是v,那么就从栈里面找边,找到出发点为v的边为止,找到的这些边都是环上的边,这个和tarjan算法的找同一个连通分量的点的道理是一样 #incl

hdu - 3594 Cactus (强连通)

http://acm.hdu.edu.cn/showproblem.php?pid=3594 判断给定的图是否是强连通的,并且每条边都只属于一个连通分量. 判断强连通只需要判断缩点之后顶点数是否为1即可, 然后在缩点的过程中,如果已经产生环,并且当前结点的父节点还有父节点,则必定有多个环, 最后还要判断每个结点都要只属于一个联通分量,否则不符合要求. 1 #include <iostream> 2 #include <cstdio> 3 #include <cmath>

HDU 3594 Cactus

题意: 一幅有向图是不是仙人掌 思路: 有向图仙人掌是强连通图且每条边最多只属于一个环 一幅有向图是仙人掌当且仅当满足3个条件: 1.dfs树无横向边 2.对于节点u的所有儿子v,它们的low[v]<=dfn[u] 3.满足low[v]<dfn[u]的v的数量num(v),u的逆向边的数量num(u),有如下关系num(v)+num(u)<2 证明见 http://download.csdn.net/detail/kksleric/4502360 代码: #include<cstd

HDU 3594 Cactus 解题报告

题意:判断题目中给出的图是否符合两个条件.1 这图只有一个强连通分量 2 一条边只能出现在一个环里. 思路:条件1的满足只需要tarjan算法正常求强连通分量即可,关键是第二个条件,我们把对边的判断转化为对点的记录,在tarjan深搜的过程中,使用fa数组记录一下搜索的过程,即每个节点的父子关系,当我们发现一条回边的时候,我们从这个点使用fa向前追溯,追溯过程中建立一个数组记录每个节点的情况,只要这个点处于一个环里,就给它加1,如果这个点的值大于了一,也就意味着有这个点同时属于两个环,同意意味着

bzoj 1023: [SHOI2008]cactus仙人掌图 tarjan索环&amp;&amp;环上单调队列

1023: [SHOI2008]cactus仙人掌图 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 1141  Solved: 435[Submit][Status] Description 如果某个无向连通图的任意一条边至多只出现在一条简单回路(simple cycle)里,我们就称这张图为仙人图(cactus).所谓简单回路就是指在图上不重复经过任何一个顶点的回路. 举例来说,上面的第一个例子是一张仙人图,而第二个不是——注意到它有三条简单回路

【BZOJ 1023】 [SHOI2008]cactus仙人掌图

1023: [SHOI2008]cactus仙人掌图 Time Limit: 1 Sec  Memory Limit: 162 MB Submit: 1235  Solved: 482 [Submit][Status] Description 如果某个无向连通图的任意一条边至多只出现在一条简单回路(simple cycle)里,我们就称这张图为仙人图(cactus).所谓简单回路就是指在图上不重复经过任何一个顶点的回路. 举例来说,上面的第一个例子是一张仙人图,而第二个不是--注意到它有三条简单

【BZOJ】【1023】【SHOI2008】cactus仙人掌图

DP/仙人掌 题解:http://hzwer.com/4645.html->http://z55250825.blog.163.com/blog/static/150230809201412793151890/ QAQ了 呃……第一次做仙人掌的题目……感觉性质还是蛮神奇的(我是不是应该先做一点环套树的题目呢?>_>) 每个点都只会在一个简单环上,所以在dfs的时候,对于一个环,它上面的点是深度连续的一段(沿着father可以遍历这个环!),然后最后一个点再指回起始点,所以只要low改变了

bzoj千题计划113:bzoj1023: [SHOI2008]cactus仙人掌图

http://www.lydsy.com/JudgeOnline/problem.php?id=1023 dp[x] 表示以x为端点的最长链 子节点与x不在同一个环上,那就是两条最长半链长度 子节点与x在同一个环上,环形DP,单调队列优化 对于每一个环,深度最小的那个点 有可能会更新 上层节点, 所以 每一个环DP完之后,更新 dp[深度最小的点] #include<cstdio> #include<iostream> #include<algorithm> using

HDOJ 题目3594 Cactus(强连通,判仙人掌图)

Cactus Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 1365    Accepted Submission(s): 654 Problem Description 1. It is a Strongly Connected graph. 2. Each edge of the graph belongs to a circle