zoukankan      html  css  js  c++  java
  • 判断强联通图中每条边是否只在一个环上(hdu3594)

    hdu3594

    Cactus

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
    Total Submission(s): 1131    Accepted Submission(s): 542


    Problem Description
    1. It is a Strongly Connected graph.
    2. Each edge of the graph belongs to a circle and only belongs to one circle.
    We call this graph as CACTUS.



    There is an example as the figure above. The left one is a cactus, but the right one isn’t. Because the edge (0, 1) in the right graph belongs to two circles as (0, 1, 3) and (0, 1, 2, 3).
     

    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
    2 4 0 1 1 2 2 0 2 3 3 2 0 0 4 0 1 1 2 2 3 3 0 1 3 0 0
    题意:

    1:强连通图

    2:图中每条边只处于一个环内

    怎么样判断一个边只在一个环内呢?其实在没有找到一个环之前的时候,有一个DFS的过程,在这个过程中每走到一个点,我们就记录一下它是有哪一个点走下来的 也就是这个点的上一层的点,等到我们找到环的时候,我们马上返回去查找,查找那个点是 out了两次以上,那么肯定有边处于两个或者两个以上环内,就不符合了

    #include"stdio.h"
    #include"string.h"
    #include"queue"
    #include"stack"
    #include"iostream"
    #include"stdlib.h"
    #define M 20005
    #define inf 999999999
    using namespace std;
    stack<int>q;
    int head[M],dfn[M],low[M],use[M],belong[M],pre[M],sum[M],flag1;
    int num,index,t,n;
    struct st
    {
        int u,v,next;
    }edge[M*3];
    void init()
    {
        t=0;
        memset(head,-1,sizeof(head));
    }
    void add(int u,int v)
    {
        edge[t].u=u;
        edge[t].v=v;
        edge[t].next=head[u];
        head[u]=t++;
    }
    void tarjan(int u)
    {
        int i;
        dfn[u]=low[u]=++index;
        q.push(u);
        use[u]=1;
        for(i=head[u];i!=-1;i=edge[i].next)
        {
            int v=edge[i].v;
            if(!dfn[v])
            {
                pre[v]=u;
                tarjan(v);
                low[u]=min(low[u],low[v]);
            }
            else if(use[v])
            {
                low[u]=min(low[u],dfn[v]);
                for(int j=u;j!=v;j=pre[j])//当发现后向边指向祖先点的时候,
                //就顺着环向上查找,把点记录在sum++中,若有点被记录了两次
                //或两次以上,则返回,肯定有边至少在两个环内;
                {
                    sum[j]++;
                    if(sum[j]>1)
                    {
                        flag1++;
                        break;
                    }
                }
            }
    
        }
        if(dfn[u]==low[u])
        {
            num++;
            int vv;
            do
            {
                vv=q.top();
                q.pop();
                use[vv]=0;
                belong[vv]=num;
            }while(vv!=u);
        }
    }
    void solve()
    {
        num=index=0;
        int i;
        memset(belong,-1,sizeof(belong));
        memset(dfn,0,sizeof(dfn));
        memset(use,0,sizeof(use));
        memset(pre,0,sizeof(pre));
        memset(sum,0,sizeof(sum));
        for(i=1;i<=n;i++)
        {
            if(!dfn[i])
            {
                tarjan(i);
            }
        }
    }
    int main()
    {
        int T,i;
        scanf("%d",&T);
        while(T--)
        {
            init();
            scanf("%d",&n);
            int x,y;
            while(scanf("%d%d",&x,&y),x||y)
            {
                x++;
                y++;
                add(x,y);
            }
            flag1=0;
            solve();
            int flag=0;
            for(i=1;i<=n;i++)
            {
                if(belong[i]!=belong[1])
                {
                    flag++;
                    break;
                }
            }
            if(flag)
                printf("NO
    ");
            else
            {
                if(flag1)
                    printf("NO
    ");
                else
                    printf("YES
    ");
            }
    
    
        }
    }
    


  • 相关阅读:
    linux UID,GID,EUID,EGID,SUID,SGID
    Hard模式题目
    【Todo】Java TreeSet学习 & ceiling,floor
    被信号打断的系统调用
    拟牛顿法——变种及其相互关系
    域名注册查询接口(API)的说明
    HDU 2825 Wireless Password(AC自动机+状压DP)
    串的模式匹配
    Android DES加密的CBC模式加密解密和ECB模式加密解密
    [Web Chart系列之五] 6. 实战draw2d之ConnectionRouter
  • 原文地址:https://www.cnblogs.com/mypsq/p/4348257.html
Copyright © 2011-2022 走看看