欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

一些题解

程序员文章站 2022-06-02 12:33:12
...

妖怪等级考试:

给定一个无向连通图,求是否存在两个点之间存在三条路径,
并要求输出路径。
首先,如果两个节点之间存在多条不相交路径,就一定存在一个环。
所以,这题和找环相关。
只有两个环之间存在相交的边,才说明有解。
如图:
一些题解
现在关键就是如何找到环。
由于无向图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;
}
相关标签: 题解