寻找道路

问题 E: 寻找道路

时间限制: 1 Sec  内存限制: 128 MB
提交: 61  解决: 9
[提交] [状态] [讨论版] [命题人:admin]

题目描述

在有向图G 中,每条边的长度均为1 ,现给定起点和终点,请你在图中找一条从起点到终点的路径,该路径满足以下条件:
1 .路径上的所有点的出边所指向的点都直接或间接与终点连通。
2 .在满足条件1 的情况下使路径最短。
注意:图G 中可能存在重边和自环,题目保证终点没有出边。
请你输出符合条件的路径的长度。

输入

第一行有两个用一个空格隔开的整数n 和m ,表示图有n 个点和m 条边。
接下来的m 行每行2 个整数x 、y ,之间用一个空格隔开,表示有一条边从点x 指向点y 。

最后一行有两个用一个空格隔开的整数s 、t ,表示起点为s ,终点为t 。

0<n≤10,000,0<m≤200,000,0<x,y,s,t≤n,x≠t。

输出

输出只有一行,包含一个整数,表示满足题目᧿述的最短路径的长度。如果这样的路径不存在,输出- 1 。

样例输入

3 2
1 2
2 1
1 3

样例输出

-1

提示

如上图所示,箭头表示有向道路,圆点表示城市。起点1 与终点3 不连通,所以满足题目描述的路径不存在,故输出- 1 。 

Solution:记录一下每个点的出度,反向建边,再从终点bfs一遍,记录终点到每个点的路径条数,如果等于出度,则满足条件1,然后用这些符合条件1的点跑最短路即可。

#include<bits/stdc++.h>
#define REP(i, a, b) for(int i = (a); i <= (b); ++ i)
#define REP(j, a, b) for(int j = (a); j <= (b); ++ j)
#define PER(i, a, b) for(int i = (a); i >= (b); -- i)
using namespace std;
const int maxn=3e5+666;
template <class T>
inline void rd(T &ret){
    char c;
    ret = 0;
    while ((c = getchar()) < '0' || c > '9');
    while (c >= '0' && c <= '9'){
        ret = ret * 10 + (c - '0'), c = getchar();
    }
}
int head[maxn],vis[maxn],head1[maxn],vis1[maxn],ex[maxn],tot[maxn],l,r,s,t,dis[maxn];
struct node{
      int u,v,nx;
}p[maxn],q[maxn];
int n,m;
void addedge(int x,int y){
     p[++l].u=y,p[l].v=x,p[l].nx=head[y],head[y]=l;
     q[++r].u=x,q[r].v=y,q[r].nx=head1[x],head1[x]=r;
}
queue<int>qu;
void bfs(){
    qu.push(t);
    vis[t]=1;
    while(qu.size()){
        int cur=qu.front();
        qu.pop();
        for(int i=head[cur];i;i=p[i].nx){
            int to=p[i].v;
            tot[to]++;
            if(!vis[to]){
                qu.push(to);
                vis[to]=1;
            }
        }
    }
}
void spfa(){
     qu.push(s);
     REP(i,1,n)dis[i]=0x3f3f3f3f;
     dis[s]=0,vis1[s]=1;
     while(qu.size()){
          int cur=qu.front();
          qu.pop();
          vis1[cur]=0;
          for(int i=head1[cur];i;i=q[i].nx){
               int to=q[i].v;
               if(dis[to]>dis[cur]+1&&ex[to]==tot[to]){
                    dis[to]=dis[cur]+1;
                    if(!vis1[to]){
                        vis1[to]=1,qu.push(to);
                    }
               }
          }
     }
}
int main(){
    rd(n),rd(m);
    REP(i,1,m){
       int a,b;
       rd(a),rd(b),ex[a]++;
       addedge(a,b);
    }
    rd(s),rd(t);
    bfs();
    spfa();
    if(dis[t]==0x3f3f3f3f)cout<<-1<<endl;
    else cout<<dis[t]<<endl;
    return 0;
}
原文地址:https://www.cnblogs.com/czy-power/p/10412533.html