NOIP2014 day2 T2 洛谷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

說明

解釋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一遍,標記所有走過的點。

如果倒着BFS不能到起點,說明不連通。

如果能到起點,則正向BFS,SPFA求單源最短路徑,途中要判斷所經歷的點都在答案路徑內(即該點所有出邊都指向之前標記過的點)

妥了

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
//
int head[500000];
int ct=0,s,t;
int used[300000],dis[300000];
int n,m,x[300000],y[300000];
//
//鄰接表處理 
struct edge{
    int next;
    int to;
}e[500000];
void add(int from,int to){
    e[++ct].to=to;
    e[ct].next=head[from];
    head[from]=ct;
    return;
}
bool pd(int pos){
    int i;
    for(i=head[pos];i;i=e[i].next){
        if(!used[e[i].to])return 0;//未與終點聯通 
    }
    return 1;
}
// 
int q[300000];
int main(){
    scanf("%d%d",&n,&m);
    int i,j;
    for(i=1;i<=m;i++){
        scanf("%d%d",&x[i],&y[i]);
        add(y[i],x[i]);//第一遍反向製表 
    }
    scanf("%d%d",&s,&t);
    //bfs
    int hd=0,tl=1;
    q[0]=t;
    used[t]=1;
    while(hd<=tl){
        int pos=q[hd];
        hd++;
        for(i=head[pos];i;i=e[i].next){
            if(!used[e[i].to]){
                q[++tl]=e[i].to;
                used[e[i].to]=1;
            }
        }
    }
    //finish
    if(!used[s]){
        printf("-1");
        return 0;
    }
    memset(head,0,sizeof(head));//再次初始化
    memset(q,0,sizeof(q));
    memset(dis,-1,sizeof(dis));
    ct=0;
    for(i=1;i<=m;i++){
        add(x[i],y[i]);
    }
    //bfs
    q[0]=s;
    dis[s]=0;
    hd=0;tl=1;
    int ans=10000;
    while(hd<=tl){//開始正向SPFA
        int pos=q[hd];
        hd++;
        if(pd(pos)==0)continue;
        for(i=head[pos];i;i=e[i].next){
            if(dis[e[i].to]    ==-1)
            {
                dis[e[i].to]=dis[pos]+1;
                q[tl++]=e[i].to;
                if(e[i].to==t){
                    ans=dis[t];
                    printf("%d",ans);//找到解輸出
                    return 0;
                }
            }
        }
    }
    //finish
    printf("-1");
    return 0;
}


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