zoukankan      html  css  js  c++  java
  • poj3713 Transferring Sylla 枚举+tarjan判割点

    其实就是判断是否为三连通图

    三连通图指的是去掉3个点就不连通的图,但是并没有直接求三连通的算法。著名的Tarjan算法可以求解连通和割点,再枚举删除一个点就能达到三连通的目的。

    先看用例2,是由用例1去掉一条边而变成非三连通图的:

    至少造成了2和3非三连通:

    我们来思考如何推导出2和3非三连通,假设从上图中删除了节点0,通过Tarjan算法,我们可以发现节点1是割点:

     

    那么只需删除从3到割点和从3到我们枚举删除的节点0的两条边,就可以将3和2分割开来:

    才删除了两条边2和3就不连通了,这个图显然不是三连通图。

    #include<stdio.h>
    #include<algorithm>
    #include<string.h>
    using namespace std;
    const int maxn = 20010;
    int cnt,flag,times,del,root;
    int head[maxn],low[maxn],dfn[maxn];
    struct no
    {
        int v,next;
    }Eg[2*maxn];
    void init( )
    {
        cnt=0;
        memset(head,-1,sizeof(head));
    }
    void add(int form,int to)
    {
        Eg[cnt].v=to;Eg[cnt].next=head[form];head[form]=cnt++;
    }
    void dfs(int u,int fa)
    {
        if(flag)
        return ;
        int tot=0;
        low[u] = dfn[u] = ++times;
        for(int i=head[u] ; i!=-1 ; i=Eg[i].next)
        {
            int v=Eg[i].v;
            if(v==fa||v==del)
            continue;
            if(!dfn[v])
            {
                tot++;
                dfs(v,u);
                low[u]=min(low[u],low[v]);
                //判断割点
                if((u==root&&tot>1)||(u!=root&&low[v]>=dfn[u]))
                    flag=1;
            }
            else
            low[u]=min(low[u],dfn[v]);
        }
    }
    int main( )
    {
        int n,m;
        while(scanf("%d%d",&n,&m)!=EOF)
        {
            if(n==0&&m==0)
                break;
        init();
        for(int i=0 ; i<m ; i++)
        {
            int u,v;
            scanf("%d%d",&u,&v);
            add(u,v);
            add(v,u);
        }
        flag=0;
        for(int i=0 ; i<n ; i++)
        {
            del = i ; times = 0;
            memset(dfn,0,sizeof(dfn));
            root = 0;
            if(del==0)
            root=1;
            dfn[del] = 1;
            dfs(root,-1);
            for(int j=0 ; j<n ; j++)
            {
                if(!dfn[j])
                {
                    flag=1;
                    break;
                }
            }
            if(flag)
                break;
        }
        if(flag)
            puts("NO");
        else
            puts("YES");
        }
        return 0;
    
    }
    View Code
  • 相关阅读:
    看美剧学英语 | Jeff Winger's speech in Community
    学习笔记 | Coursera
    学习笔记 | Coursera
    Python: How to reverse a list in python
    公司接口流程
    使用Supervisor管理Django应用进程
    orm中 如何模糊匹配某一年的用户和某一事时间段的用户
    Linux如何查看进程是否存活
    项目中有 xxxx 不能被json序列化
    关于项目经验
  • 原文地址:https://www.cnblogs.com/shuaihui520/p/9309461.html
Copyright © 2011-2022 走看看