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<cstdio>
#include<iostream>
#include<string>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<map>
#include<set>
#include<vector>
using namespace std;
typedef __int64 LL;
#define N 20010
#define M 50010
#define inf 2147483647

int t,n,tot,idx;
int head[N],dfn[N],low[N],instack[N];
struct edge
{
    int v,next;
}ed[M];
bool ans;

void add(int u,int v)
{
    ed[tot].v=v;
    ed[tot].next=head[u];
    head[u]=tot++;
}

void tarjan(int u)
{
    int i,v,num=0;
    dfn[u]=low[u]=++idx;
    instack[u]=1;
    for(i=head[u];~i;i=ed[i].next)
    {
        v=ed[i].v;
        if(dfn[v]==-1)
        {
            tarjan(v);
			low[u]=min(low[u],low[v]);
        }
        else
        {
            if(instack[v]) low[u]=min(low[u],dfn[v]);
            else ans=false;
        }
    }
    for(i=head[u];~i;i=ed[i].next)
    {
        v=ed[i].v;
        if(dfn[v]<dfn[u]) num++;
        else
        {
            if(low[v]>dfn[u]) ans=false;
            else if(low[v]<dfn[u]) num++;
        }
    }
    if(num>1) ans=false;
}

void solve()
{
    ans=true;
    idx=0;
    memset(dfn,-1,sizeof(dfn));
	memset(instack,0,sizeof(instack));
	tarjan(0);
    for(int i=1;i<n;i++)
        if(dfn[i]==-1) ans=false;
}

int main()
{
    int i,u,v;
    scanf("%d",&t);
    while(t--)
    {
        tot=0;
        memset(head,-1,sizeof(head));
        scanf("%d",&n);
        while(~scanf("%d%d",&u,&v))
        {
            if(!u&&!v) break;
            add(u,v);
        }
        solve();
        if(ans) puts("YES");
        else puts("NO");
    }
    return 0;
}
时间: 2024-10-19 02:55:06

HDU 3594 Cactus的相关文章

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&l

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 解题报告

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

HDU - 3594 Cactus(仙人掌图)

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

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

hdu 3594 强连通分量加环

传送门:Cactus 判断给定的有向图是否满足 1.强连通 2 每一条边属于且仅属于一个环?YES:NO 存在有两种情况(yy一下) 1.他的子节点在栈中 2.他的子节点的最早的时间戳不是他 #include <stdio.h> #include <string.h> #include <vector> #include <stack> #include <algorithm> using namespace std; #define N 200

图论 500题——主要为hdu/poj/zoj

转自——http://blog.csdn.net/qwe20060514/article/details/8112550 =============================以下是最小生成树+并查集======================================[HDU]1213   How Many Tables   基础并查集★1272   小希的迷宫   基础并查集★1325&&poj1308  Is It A Tree?   基础并查集★1856   More i

hdu图论题目分类

=============================以下是最小生成树+并查集====================================== [HDU] 1213 How Many Tables 基础并查集★ 1272 小希的迷宫 基础并查集★ 1325&&poj1308 Is It A Tree? 基础并查集★ 1856 More is better 基础并查集★ 1102 Constructing Roads 基础最小生成树★ 1232 畅通工程 基础并查集★ 123

题单二:图论500

http://wenku.baidu.com/link?url=gETLFsWcgddEDRZ334EJOS7qCTab94qw5cor8Es0LINVaGMSgc9nIV-utRIDh--2UwRLvsvJ5tXFjbdpzbjygEdpGehim1i5BfzYgYWxJmu ==========  以下是最小生成树+并查集=========================[HDU]1213         How Many Tables        基础并查集★1272         小