寻找道路

题面

首先,预处理,把每条边反向。

从终点开始bfs,标记从终点开始可以走到的点。

第二步,枚举每一个点,如果这个点没有被标记,则枚举它的每一条出边(反向后的),如果它指向的点被标记,则说明这个被标记的点不合法,删除。

第三步,在合法点上bfs,单源最短路。

#include<bits/stdc++.h>
using namespace std;
int read()
{
    int x=0,y=1;char c=getchar();
    while(c>'9'||c<'0'){if(c=='0')y=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    return x*y;
}
int n,m;
vector<int>v[10005];
bool cando[10005],er[10005];
queue<int>q;
int st,ed;
int ans[10005];
int main()
{    
    n=read(),m=read();
    for(int i=1;i<=m;i++)
    {
        int a=read(),b=read();
        if(a==b)continue;
        v[b].push_back(a);
    }
    st=read(),ed=read();
    cando[ed]=1;
    q.push(ed);
    while(!q.empty())
    {
        int no=q.front();
        q.pop();
        for(int i=0,j=v[no].size();i<j;i++)
            if(!cando[v[no][i]]){cando[v[no][i]]=1;q.push(v[no][i]);}
    }
    memcpy(er,cando,sizeof(cando));
    for(int i=1;i<=n;i++)
        if(!cando[i])
            for(int j=0,k=v[i].size();j<k;j++)
                if(er[v[i][j]])
                    er[v[i][j]]=0;
    q.push(ed);
    while(!q.empty())
    {
        int no=q.front();
        q.pop();
        for(int i=0,j=v[no].size();i<j;i++)
            if(er[v[no][i]])
            {
                q.push(v[no][i]);
                er[v[no][i]]=0;
                ans[v[no][i]]=ans[no]+1;
            }
    }
    if(ans[st]==0)printf("-1");
    else printf("%d",ans[st]);
    return 0;
}

  

posted @ 2019-09-08 13:24  [jackeylove]  阅读(122)  评论(0编辑  收藏  举报