码迷,mamicode.com
首页 > 其他好文 > 详细

模拟赛 妖怪等级考试 题解

时间:2019-07-25 20:29:30      阅读:92      评论:0      收藏:0      [点我收藏+]

标签:math   std   题解   --   else   inf   mat   alt   printf   

妖怪等级考试:

给定一个无向连通图,求是否存在两个点之间存在三条路径,
并要求输出路径。
首先,如果两个节点之间存在多条不相交路径,就一定存在一个环。
所以,这题和找环相关。
只有两个环之间存在相交的边,才说明有解。
如图:
技术图片

现在关键就是如何找到环。
由于无向图dfs后,只有树边和返祖边,且只有返祖边才会形成环,所以只要对返祖边处理就可以了。
每次将第个\(i\)环上所有边染成\(i\)色,当有一个边被染成两种颜色时,就找到了解。
因为每条边最多被染一次就会出现解,所以染色可以暴力进行。
如图:
技术图片

输出解时考虑三种情况就可以了。

#include <stdio.h>
int fr[100010],ne[400010];
int v[400010],bs=0,fa[100010];
bool fz[400010];
int hu[400010],fb[100010];
int h2,x[400010],dfn[100010],tm=0;
int sd[100010],jg[100010];
void addb(int a,int b)
{
    x[bs]=a;
    v[bs]=b;
    ne[bs]=fr[a];
    fr[a]=bs;
    hu[bs]=-1;
    bs+=1;
}
int dfs(int u,int f)
{
    sd[u]=sd[f]+1;
    fa[u]=f;
    tm+=1;
    dfn[u]=tm;
    for(int i=fr[u];i!=-1;i=ne[i])
    {
        if(v[i]==f)
            continue;
        if(dfn[v[i]]==0)
        {
            fb[v[i]]=i;
            int t=dfs(v[i],u);
            if(t!=-1)
                return t;
        }
        else if(dfn[v[i]]<dfn[u])
        {
            int t=u;
            while(t!=v[i])
            {
                if(hu[fb[t]]!=-1)
                {
                    h2=i;
                    return fb[t];
                }
                hu[fb[t]]=i;
                t=fa[t];
            }
        }
    }
    return -1;
}
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
        fr[i]=-1;
    for(int i=0;i<m;i++)
    {
        int a,b;
        scanf("%d%d",&a,&b);
        addb(a,b);
        addb(b,a);
    }
    int rt=dfs(1,-1);
    if(rt==-1)
        printf("NO");
    else
    {
        printf("YES\n");
        int t=v[hu[rt]];
        if(sd[v[h2]]>sd[t])
            t=v[h2];
        int z=v[rt],s=0;
        while(1)
        {
            s+=1;
            if(z==t)
                break;
            z=fa[z];
        }
        printf("%d ",s);
        z=v[rt];
        while(1)
        {
            printf("%d ",z);
            if(z==t)
                break;
            z=fa[z];
        }
        printf("\n");
        int a1=v[h2],a2=v[hu[rt]];
        z=t,s=0;
        while(1)
        {
            jg[s]=z;
            s+=1;
            if(z==a1)
                break;
            z=fa[z];
        }
        z=x[h2];
        while(1)
        {
            jg[s]=z;
            s+=1;
            if(z==v[rt])
                break;
            z=fa[z];
        }
        printf("%d ",s);
        for(int i=s-1;i>=0;i--)
            printf("%d ",jg[i]);
        printf("\n");
        z=t,s=0;
        while(1)
        {
            jg[s]=z;
            s+=1;
            if(z==a2)
                break;
            z=fa[z];
        }
        z=x[hu[rt]];
        while(1)
        {
            jg[s]=z;
            s+=1;
            if(z==v[rt])
                break;
            z=fa[z];
        }
        printf("%d ",s);
        for(int i=s-1;i>=0;i--)
            printf("%d ",jg[i]);
    }
    return 0;
}

模拟赛 妖怪等级考试 题解

标签:math   std   题解   --   else   inf   mat   alt   printf   

原文地址:https://www.cnblogs.com/lnzwz/p/11246711.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!