洛谷-2296 寻找道路

题目描述
在有向图 G 中,每条边的长度均为 1,现给定起点和终点,请你在图中找一条从起点到终点的路径,该路径满足以下条件:
路径上的所有点的出边所指向的点都直接或间接与终点连通。
在满足条件1的情况下使路径最短。
注意:图 G 中可能存在重边和自环,题目保证终点没有出边。
请你输出符合条件的路径的长度。
输入输出格式
输入格式:
第一行有两个用一个空格隔开的整数 n 和 m,表示图有 n 个点和 m 条边。
接下来的 m 行每行 2 个整数 x,y,之间用一个空格隔开,表示有一条边从点 x 指向点y。
最后一行有两个用一个空格隔开的整数 s,ts, ts,t,表示起点为 s,终点为 t。
输出格式:
输出只有一行,包含一个整数,表示满足题目描述的最短路径的长度。如果这样的路径不存在,输出−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

解释:可以先把不满足条件的点给去掉,对剩下的图求一遍最短路就好了。我们可以建立反向边。从t进行最短路,不能到达的点就是不满足的点。再重新正向建图,如果直接指向不满足的点,也作为不满足点。最后对满足的点建图就OK

#include<stdio.h>
#include<queue>
#include<cstring>
#include<iostream>
#include<cstdlib>
#define N 10005
#define M 200003
#define INF 200003
using namespace std;
int head[N]={0};
int next1[M]={0};
int V[M]={0};
bool vis[N]={0};
int W[M]={0};
int tot=0;
int dist[N]={0};
int a[M]={0},b[M]={0};
bool H[N]={0};
int n=0,m=0,s=0,t=0;
void add(int x,int y,int c){
    tot++;
    next1[tot]=head[x];
    V[tot]=y;W[tot]=c;
    head[x]=tot;
}
priority_queue<pair<int,int> > que;
void dij(int x){
    fill(dist,dist+N,INF);
    memset(vis,0,sizeof(vis));
    dist[x]=0;
    que.push(make_pair(0,x));
    while(que.size()){
        pair<int,int> temp=que.top();que.pop();
        int from=temp.second;if(vis[from]) continue;
        vis[from]=true;
        for(int i=head[from];i;i=next1[i]){
            int to=V[i],w=W[i];
            if(dist[to]>dist[from]+w){
                dist[to]=dist[from]+w;
                que.push(make_pair(-dist[to],to));
            }
        }
    }
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++){
        scanf("%d%d",&a[i],&b[i]);
        add(b[i],a[i],1);
    }
    scanf("%d%d",&s,&t);
    dij(t);
    memset(head,0,sizeof(head));tot=0;
    for(int i=1;i<=m;i++) add(a[i],b[i],1);
    for(int i=1;i<=n;i++){
        int temp=dist[i];
        for(int j=head[i];j;j=next1[j]){
            int to=V[j];
            temp=max(temp,dist[to]);
        }
        if(temp>=INF) H[i]=1;
    }
    memset(head,0,sizeof(head));tot=0;
    for(int i=1;i<=m;i++){
        if(H[a[i]]||H[b[i]]) continue;
        add(a[i],b[i],1);
    }
    dij(s);
    if(dist[t]>=INF) printf("-1\n");
    else printf("%d\n",dist[t]);
    return 0;
}



猜你喜欢

转载自blog.csdn.net/mkopvec/article/details/92388164