问题 E: 寻找道路
时间限制: 1 Sec 内存限制: 128 MB提交: 61 解决: 9
[提交] [状态] [讨论版] [命题人:admin]
题目描述
在有向图G 中,每条边的长度均为1 ,现给定起点和终点,请你在图中找一条从起点到终点的路径,该路径满足以下条件:
1 .路径上的所有点的出边所指向的点都直接或间接与终点连通。
2 .在满足条件1 的情况下使路径最短。
注意:图G 中可能存在重边和自环,题目保证终点没有出边。
请你输出符合条件的路径的长度。
1 .路径上的所有点的出边所指向的点都直接或间接与终点连通。
2 .在满足条件1 的情况下使路径最短。
注意:图G 中可能存在重边和自环,题目保证终点没有出边。
请你输出符合条件的路径的长度。
输入
第一行有两个用一个空格隔开的整数n 和m ,表示图有n 个点和m 条边。
接下来的m 行每行2 个整数x 、y ,之间用一个空格隔开,表示有一条边从点x 指向点y 。
接下来的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; }