洛谷 P2296 尋找道路

題目描述
在有向圖G 中,每條邊的長度均爲1 ,現給定起點和終點,請你在圖中找一條從起點到終點的路徑,該路徑滿足以下條件:
1 .路徑上的所有點的出邊所指向的點都直接或間接與終點連通。
2 .在滿足條件1 的情況下使路徑最短。
注意:圖G 中可能存在重邊和自環,題目保證終點沒有出邊。
請你輸出符合條件的路徑的長度。
輸入輸出格式
輸入格式:
輸入文件名爲road .in。
第一行有兩個用一個空格隔開的整數n 和m ,表示圖有n 個點和m 條邊。
接下來的m 行每行2 個整數x 、y ,之間用一個空格隔開,表示有一條邊從點x 指向點y 。最後一行有兩個用一個空格隔開的整數s 、t ,表示起點爲s ,終點爲t 。
輸出格式:
輸出文件名爲road .out 。
輸出只有一行,包含一個整數,表示滿足題目᧿述的最短路徑的長度。如果這樣的路徑不存在,輸出- 1 。
輸入輸出樣例
輸入樣例#1:
3 2  
1 2  
2 1  
1 3  
輸出樣例#1:
-1
輸入樣例#2:
6 6  
1 2  
1 3  
2 6  
2 5  
4 5  
3 4  
1 5  
輸出樣例#2:

3

題解:一開始寫了個拓撲排序跪了,想一想還是很有道理的。反向建圖,對於入度爲0,刪掉改點,並將改點所連得點標記,只能標記不能刪除(就是這跪了),但若刪掉改點後其連接的點入度爲0,繼續刪,這就是拓撲排序的思想。然後bfs,被標記的點不能走。

總結:對於圖論題中要對圖的結構進行調整時一定要考慮影響,如果有反面影響,一定不能改。

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <queue>
#define N 300000
#define inf (1<<28)
using namespace std;
queue<int> q;
int n,m,dis[N],rd[N];
int last[N],to[N],head[N],cnt=0;
bool vis[N];
void ins(int u,int v){
	last[++cnt]=head[u];head[u]=cnt;to[cnt]=v;
}
int main(){
//	freopen("in.txt","r",stdin);
	int u,v,s,t,tmp;
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++) dis[i]=inf;
	for(int i=1;i<=m;i++){
		scanf("%d%d",&v,&u);
		ins(u,v);rd[v]++;
	}
	scanf("%d%d",&s,&t);
	for(int i=1;i<=n;i++){
		if(!rd[i] && i!=t)
		    q.push(i),vis[i]=1;
	}
	while(!q.empty()){
		tmp=q.front();q.pop();
		for(int i=head[tmp];i;i=last[i]){
			rd[to[i]]--;vis[to[i]]=1;
			if(!rd[to[i]]) q.push(to[i]);
		}
    }
    q.push(t);dis[t]=0;
    while(!q.empty()){
    	tmp=q.front();q.pop();
    	if(tmp==s){
    		printf("%d",dis[s]);return 0;
		}
		for(int i=head[tmp];i;i=last[i]){
			if(vis[to[i]] || dis[to[i]]<dis[tmp]+1) continue;
			dis[to[i]]=dis[tmp]+1;
			q.push(to[i]);
		}
	}
	cout<<"-1"<<endl;
	return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章