P2296 [NOIP2014]寻找道路-图论,最短路,bfs

版权声明:原创,勿转 https://blog.csdn.net/qq_42386465/article/details/82832092

在有向图 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;
}

猜你喜欢

转载自blog.csdn.net/qq_42386465/article/details/82832092