NOIP2014提高组-day2-2——寻找道路(。。。。这算什么题呢。。?最短路?)
在有向图G中,每条边的长度均为1,现给定起点和终点,请你在图中找一条从起点到终点的路径,该路径满足以下条件:
1.路径上的所有点的出边所指向的点都直接或间接与终点连通。 2.在满足条件1的情况下使路径最短。
注意:图G中可能存在重边和自环,题目保证终点没有出边。
请你输出符合条件的路径的长度。
输入
第一行有两个用一个空格隔开的整数n和m,表示图有n个点和m条边。 接下来的m行每行2个整数x、y,之间用一个空格隔开,表示有一条边从点x指向点y。
最后一行有两个用一个空格隔开的整数s、t,表示起点为s,终点为t。
输出
输出只有一行,包含一个整数,表示满足题目描述的最短路径的长度。如果这样的路径不存在,输出- 1。
样例输入
3 2
1 2
2 1
1 3
road.in
6 6
1 2
1 3
2 6
2 5
4 5
3 4
1 5
样例输出
-1
样例2:
road.out
3
考虑到所有点的出边都必须和终点相连
那我们在建有向图的时候也建一个反向图
那我们可以先从终点沿反向图dfs一次,把所有能走到的点标出来
然后从起点开始跑最短路
每次对于一个新的点,我们先枚举其所有出去的点,如果有的点没有被标出来
那么这个点显然是不能走
continue就可以了
#include<bits/stdc++.h>
using namespace std;
#define ll long long
inline int read(){
char ch=getchar();
int res=0;
while(!isdigit(ch))ch=getchar();
while(isdigit(ch))res=(res<<3)+(res<<1)+(ch^48),ch=getchar();
return res;
}
const int N=10005;
const int M=200005;
int n,m,adj[N],nxt[M],to[M],dis[N],head[N],go[M],nec[M],str,des,cnt,tot;
bool vis[N],pas[N];
inline void addedge(int u,int v){
nxt[++cnt]=adj[u],adj[u]=cnt,to[cnt]=v;
nec[++tot]=head[v],head[v]=tot,go[tot]=u;
}
inline void dfs(int u){
for(int e=head[u];e;e=nec[e]){
int v=go[e];
if(pas[v])continue;
pas[v]=true;
dfs(v);
}
}
priority_queue<pair<int,int>,vector<pair<int,int> >,greater<pair<int,int> > >q;
inline void dijkstra(){
memset(dis,127,sizeof(dis));
q.push(make_pair(0,str));dis[str]=0;
while(!q.empty()){
int u=q.top().second;q.pop();
if(vis[u])continue;vis[u]=true;
bool flag=true;
for(int e=adj[u];e;e=nxt[e]){
int v=to[e];
if(!pas[v])flag=false;
}
if(!flag)continue;
for(int e=adj[u];e;e=nxt[e]){
int v=to[e];
if(dis[u]+1<dis[v]){
dis[v]=dis[u]+1;
q.push(make_pair(dis[v],v));
}
}
}
}
int main(){
n=read(),m=read();
for(int i=1;i<=m;i++){
int u=read(),v=read();
addedge(u,v);
}
str=read(),des=read();pas[des]=1;
dfs(des);
dijkstra();
if(dis[des]<1000000000)
cout<<dis[des];
else cout<<"-1";
}