【NOIP2014提高組】尋找道路
題目背景
NOIP2014 提高組 Day2 試題。
題目描述
在有向圖 G 中,每條邊的長度均為 1,現給定起點和終點,請你在圖中找一條從起點到終點的路徑,該路徑滿足以下條件: 1.路徑上的所有點的出邊所指向的點都直接或間接與終點連通。 2.在滿足條件 1 的情況下使路徑最短。 注意:圖 G 中可能存在重邊和自環,題目保證終點沒有出邊。 請你輸出符合條件的路徑的長度。
輸入格式
第一行有兩個用一個空格隔開的整數 n 和 m,表示圖有 n 個點和 m 條邊。 接下來的 m 行每行 2 個整數 x、y,之間用一個空格隔開,表示有一條邊從點 x 指向點y。 最後一行有兩個用一個空格隔開的整數 s、t,表示起點為 s,終點為 t。
輸出格式
輸出只有一行,包含一個整數,表示滿足題目描述的最短路徑的長度。如果這樣的路徑不存在,輸出 -1。
樣例資料 1
輸入
3 2 1 2 2 1 1 3
輸出
-1
樣例資料 2
輸入
6 6 1 2 1 3 2 6 2 5 4 5 3 4 1 5
輸出
3
備註
【樣例1說明】
如上圖所示,箭頭表示有向道路,圓點表示城市。起點 1 與終點 3 不連通,所以滿足題目描述的路徑不存在,故輸出 -1。
【樣例2說明】
如上圖所示,滿足條件的路徑為 1->3->4->5。注意點 2 不能在答案路徑中,因為點 2 連了一條邊到點 6,而點 6 不與終點 5 連通。
【資料說明】 對於 30% 的資料,0<n≤10,0 <m≤20; 對於 60% 的資料,0<n≤100,0 <m≤2000; 對於 100% 的資料,0<n≤10,000,0<m≤200,000,0<x,y,s,t≤n,x≠t。
解析:
題解是BFS,而我用的是另一種方法。
如果沒有限制一,那麼就是一道最短路的板題,其實對於限制一,我們只需要將與出度為0且不是終點的點相連的點標記不能走,然後直接最短路,就可以了。為什麼是對的?稍微畫圖想想你就明白了。
程式碼:
#include <bits/stdc++.h> using namespace std; const int Maxn=10005; const int Maxm=200005; const int inf=1e9; int n,m,size,s,t; int first[Maxn],First[Maxn],v[Maxn],pre[Maxn],dis[Maxn],to[Maxn],vis[Maxn]; struct shu{int to,next;}; shu edge[Maxm<<1],Edge[Maxm<<1]; inline int get_int() { int x=0,f=1; char c; for(c=getchar();(!isdigit(c))&&(c!='-');c=getchar()); if(c=='-') f=-1,c=getchar(); for(;isdigit(c);c=getchar()) x=(x<<3)+(x<<1)+c-'0'; return x*f; } inline void build(int x,int y) { edge[++size].next=first[x]; first[x]=size; edge[size].to=y; Edge[size].next=First[y]; First[y]=size; Edge[size].to=x; } inline void dfs(int point) { for(int u=First[point];u;u=Edge[u].next) { int to=Edge[u].to; first[to]=0; } } inline void dijkstra() { priority_queue<pair<int,int> >q; for(int i=1;i<=n;i++) dis[i]=inf; dis[s]=0,q.push(make_pair(0,s)); while(q.size()) { int point=q.top().second; q.pop();if(vis[point]) continue;vis[point]=1; for(int u=first[point];u;u=edge[u].next) { int to=edge[u].to; if(dis[to] > dis[point] + 1) { dis[to]=dis[point]+1; q.push(make_pair(-dis[to],to)); } } } } int main() { n=get_int(),m=get_int(); for(int i=1;i<=m;i++) { int x=get_int(),y=get_int(); build(x,y),to[x]++; } s=get_int(),t=get_int(); for(int i=1;i<=n;i++) if(!to[i] && i!=t) dfs(i); dijkstra(); if(dis[t]==inf) cout<<"-1\n"; else cout<<dis[t]<<"\n"; return 0; }