2014年 寻找道路

//两遍BFS
//将边反向; 
//第一遍BFS搜索t能到达的的点,标记不能到的点;
//将t不能到达的点的相邻点标记不能到达;
//第二遍BFS寻找通过能到的点到达s点的最短距离;
//感觉用邻接矩阵有点危险,就顺便练了一下边表; 
#include<cstdio>
#include<queue>
using namespace std;
int n,m,s,t,x,y;
int di[10002],to[200002],be[200002],b[200002];
//di[i]保存第i个点最后读入的点;
//to[i]读入的第i条边反向后的终点;
//be[i]读入的第i条边反向后的起点;
//b[i]与读入的第i条边相同起点(反向后的)的上一次读入的边;
//具体操作看程序; 
int sz[10002];       //sz[i]表示第i个结点到达t的最短距离;
bool f[10002];
void find(int x,bool z){
    queue<int> q;
    q.push(x);
    if(z){
        f[x]=1;
        while(!q.empty()){
            int now=di[q.front()];
            while(now!=0){
                if(f[to[now]]==0) q.push(to[now]);
                f[to[now]]=1;
                now=b[now];
            }
            q.pop();
        }
    }
    else{
        while(!q.empty()){
            int now=di[q.front()];
            while(now!=0){
                if(f[to[now]]&&(sz[to[now]]>sz[q.front()]+1||sz[to[now]]==0)){
                    sz[to[now]]=sz[q.front()]+1;
                    q.push(to[now]);
                }
                now=b[now];
            }
            q.pop();
        }
    }
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++){
        scanf("%d%d",&x,&y);
        be[i]=y;
        to[i]=x;             //反向;
        b[i]=di[y];
        di[y]=i;
    }
    scanf("%d%d",&s,&t);
    find(t,1);
    queue<int> qu;
    for(int i=1;i<=n;i++) if(f[i]==0) qu.push(i);
    while(!qu.empty()){
        int now=di[qu.front()];
        while(now!=0){
            f[to[now]]=0;
            now=b[now];
        }
        qu.pop();
    }
    find(t,0);
    if(sz[s]!=0) printf("%d
",sz[s]);
    else printf("-1
");
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/qingang/p/5317117.html