NOIP2014提高組-day2-2——尋找道路(。。。。這算什麼題呢。。?最短路?)
阿新 • • 發佈:2018-12-20
在有向圖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";
}