HDU 3594 Cactus (仙人掌图、Tarjan)

网友投稿 638 2022-10-03

HDU 3594 Cactus (仙人掌图、Tarjan)

HDU 3594 Cactus (仙人掌图、Tarjan)

Description

Input

The input consists of several test cases. The first line contains an integer T (1<=T<=10), representing the number of test cases.For each case, the first line contains a integer n (1<=n<=20000), representing the number of points.The following lines, each line has two numbers a and b, representing a single-way edge (a->b). Each case ends with (0 0).Notice: The total number of edges does not exceed 50000.

Output

For each case, output a line contains “YES” or “NO”, representing whether this graph is a cactus or not.

Sample Input

240 11 22 02 33 20 040 11 22 33 01 30 0

Sample Output

YESNO

题意

给出一张有向图,判断其是否是仙人掌图。

思路

在解决这道题之前我们首先要知道什么是仙人掌图。

直观的说,仙人掌图就是一个一个的圈直接“粘”在一起的图,圈之间没有公共边。

我们主要根据其以下三点性质来做出判断:

仙人掌图的 DFS 树没有横向边​​Low(u)<=DFN(v)​​ (u 是 v 的儿子)设某个点 v 有 a(v) 个儿子的 Low 值小于 DFN(v) ,同时 v 自己有 b(v) 条逆向边,那么​​a(v)+b(v)<2​​

而 ​​LOW​​​ 与 ​​DFN​​​ 之前我们所学习的 ​​Tarjan​​ 算法中已经遇到了,直接拿来改改就可以了。

AC 代码

#include#include#include#include#include#includeusing namespace std;const int maxn = 51000;int DFN[maxn]; //记录搜索到该点的时间int LOW[maxn]; //记录当前搜索的强连通子图搜索树的根节点int Stack[maxn],Stop; //工作栈int Dindex; //一个计数器,记录访问节点的次序bool instack[maxn]; //记录当前点是否在栈中bool ans;struct node{ int to; int next;} edge[maxn];int head[maxn],tot,n;void init(){ memset(head,-1,sizeof(head)); memset(DFN,0,sizeof(DFN)); memset(instack,false,sizeof(instack)); tot=Dindex=Stop=0; ans=true;}void addedge(int u,int v){ edge[tot].to=v; edge[tot].next=head[u]; head[u]=tot++;}void tarjan(int i){ DFN[i]=LOW[i]=++Dindex; instack[i]=true; Stack[++Stop]=i; int cnt=0; for(int k=head[i]; k!=-1; k=edge[k].next) { int j=edge[k].to; if (!DFN[j]) //如果邻接的该点没有被标记 { tarjan(j); if (LOW[j]DFN[i]) //仙人掌第二条性质 { ans=false; return; } if(DFN[j]DFN[i]&&LOW[j]1) { ans=false; return; } if (DFN[i]==LOW[i]) //相等说明i为强连通子图搜索树的根节点 { int top; do //退栈 { top=Stack[Stop--]; instack[top]=false; } while (top!=i); }}int main(){ ios::sync_with_stdio(false); int T; cin>>T; while(T--) { init(); cin>>n; while(true) { int a,b; cin>>a>>b; if(a==0&&b==0)break; addedge(a,b); } tarjan(0); cout<<(ans?"YES":"NO")<

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:支付宝里怎么创建小程序(怎么在支付宝创建小程序)
下一篇:TiDB-WebAssembly 原理与实现技术详解
相关文章

 发表评论

暂时没有评论,来抢沙发吧~