P2296 [NOIP2014]尋找道路-圖論,最短路,bfs

在有向圖 G中,每條邊的長度均爲 1,現給定起點和終點,請你在圖中找一條從起點到終點的路徑,該路徑滿足以下條件:

  1. 路徑上的所有點的出邊所指向的點都直接或間接與終點連通。
  2. 在滿足條件1的情況下使路徑最短。

注意:圖 G 中可能存在重邊和自環,題目保證終點沒有出邊。

請你輸出符合條件的路徑的長度。

https://www.luogu.org/problemnew/show/P2296

1、見兩個圖,一正一反

2、反向跑bfs,處理出所有能到達終點的點

3、再複製一個的數組,枚舉每一個點,如果這個點沒有被標記,則枚舉它的每一條出邊(反向後的),如果它指向的點被標記,則說明這個被標記的點不合法,刪除。

坑點:最好有第二個數組標記,在一個數組裏刪點有後效型,如果一個點開始被標記,它通過一個序號比它小的點刪除了, 那麼訪問到它的時候,就會被當成開始就沒被標記的點,會通過它把合法點刪除。 這樣做完之後,合法點都被標記了。

4、正向跑spfa,每次鬆弛操作時判斷一下那個點是否合法即可!

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#define inf 2139062143
using namespace std;
int inline read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
struct node
{
    int next,to;
}e1[400001],e2[400001];
int head1[100001],head2[100001],dis[100001];
bool v[100001],vv[100001],vis[100001];
int n,m,cnt1,cnt2,s,t;
queue<int> q;
void add1(int x,int y)
{
    e1[++cnt1].next=head1[x];
    e1[cnt1].to=y;
    head1[x]=cnt1;
}
void add2(int x,int y)
{
    e2[++cnt2].next=head2[x];
    e2[cnt2].to=y;
    head2[x]=cnt2;
}
void bfs()
{
    q.push(t);
    v[t]=true;
    while(!q.empty()){
        int now=q.front();q.pop();
        for(int i=head2[now];i;i=e2[i].next){
            if(!v[e2[i].to]){
                v[e2[i].to]=true;
                q.push(e2[i].to);
            }
        }
    }
    memcpy(vv,v,sizeof(v));
    for(int i=1;i<=n;i++){
        if(!v[i]){
            for(int j=head2[i];j;j=e2[j].next){
                if(vv[e2[j].to])
                    vv[e2[j].to]=false;
            }
        }
    }
}
void spfa()
{
    memset(dis,127,sizeof(dis));
    q.push(s);
    dis[s]=0;
    vis[s]=true;
    while(!q.empty()){
        int now=q.front();q.pop();vis[now]=false;
        for(int i=head1[now];i;i=e1[i].next){
            int to=e1[i].to;
            if(dis[to]>dis[now]+1&&vv[to]){
                dis[to]=dis[now]+1;
                if(!vis[to]){
                    q.push(to);
                    vis[to]=true;
                }
            }
        }
    }
}
int main()
{
    n=read();m=read();
    for(int i=1;i<=m;i++){
        int x=read(),y=read();
        if(x==y) continue;
        add1(x,y);add2(y,x);
    }
    s=read();t=read();
    bfs();
    spfa();
    if(dis[t]==inf){
        printf("-1");
    }
    else{
        printf("%d",dis[t]);
    }
    return 0;
}

 

 

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