街道赛跑

 

首先第一问不难做到,我们可以去掉当前这个点,然后进行bfs,如果去掉之后当前这个点从起点不能到达终点,那个这个点就是必经路口;

那么针对第二问,我们首先能看出来是不可避免的路口(称为s集合),那么s集合中的点一定是第一问中的必经路口,很显然叭;

那么我们可以两步找到这个点,首先从起点开始bfs,标记所能到达的所有点,然后从当前枚举的必经路口中的点开始bfs,并且标记;

最后我们寻找0-n中的点s如果既没有被起点标记,又没有被当前点标记,那么当前枚举的这个点就是s集合中的点;

提供工整的代码

#include<bits/stdc++.h>
using namespace std;
inline int read()
{
    int x=0,f=1;
    char ch=getchar();
    while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    return x*f;
}
int h[5100],g[5100][5100],vis1[5100],n,vis2[5100],ans1[5100],ans2[5100],x,head,tail,tot,sum;
int main()
{
    x=read();
    while(x!=-1)
    {
        while(x!=-1&&x!=-2)
        {
            g[n][x]=1;
            x=read();
        }
        n++;
        x=read();
    }
    n--;
    for(int i=1;i<=n-1;i++)
    {
        memset(vis1,0,sizeof(vis1));
        head=1;tail=1;
        h[head]=0;
        vis1[i]=1,vis1[0]=1;
        while(head<=tail)
        {
            int k=h[head];
            head++;
            for(int z=1;z<=n;z++)
            {
                if(g[k][z]&&vis1[z]==0) 
                {
                    h[++tail]=z;
                    vis1[z]=1;
                }
            }
        }
        if(!vis1[n])
        {
            tot++;
            ans1[tot]=i;
        }
    }
    cout<<tot<<' ';
    for(int i=1;i<=tot;i++) cout<<ans1[i]<<' ';
    cout<<endl;    
    for(int i=1;i<=tot;i++)
    {
        memset(vis1,0,sizeof(vis1));
        memset(vis2,0,sizeof(vis2));
        vis1[ans1[i]]=1;vis1[0]=1;
        vis2[ans1[i]]=1;
        head=1;tail=1;
        h[head]=0;
        while(head<=tail)
        {
            int m=h[head];
            head++;
            for(int z=0;z<=n;z++)
            {
                if(g[m][z]&&!vis1[z])
                {
                    vis1[z]=1;
                    h[++tail]=z;
                }
            }
        }
        head=1;tail=1;
        h[head]=ans1[i];
        while(head<=tail)
        {
            int k=h[head];
            head++;
            for(int z=0;z<=n;z++)
            {
                if(g[k][z]&&!vis2[z])
                {
                    h[++tail]=z;
                    vis2[z]=1;
                }
            }
        }
        int b=1;
        for(int s=0;s<=n;s++)
        {
            if(s!=ans1[i]&&vis1[s]&&vis2[s])
            {
                b=0;
                break;
            }
        }
        if(b)    ans2[++sum]=ans1[i];
    }
    cout<<sum<<' ';
    for(int i=1;i<=sum;i++)
    cout<<ans2[i]<<' ';
    return 0;
}
View Code

 

posted @ 2019-01-07 13:50  Tyouchie  阅读(233)  评论(0编辑  收藏  举报