P2296 寻找道路(dfs+spfa)

洛谷 P2296 寻找道路

题目描述

在有向图 GG 中,每条边的长度均为 11,现给定起点和终点,请你在图中找一条从起点到终点的路径,该路径满足以下条件:

路径上的所有点的出边所指向的点都直接或间接与终点连通。
在满足条件 1 1的情况下使路径最短。
注意:图 GG 中可能存在重边和自环,题目保证终点没有出边。

请你输出符合条件的路径的长度。

输入输出格式
输入格式:

第一行有两个用一个空格隔开的整数 nn 和 mm,表示图有 nn 个点和 mm 条边。

接下来的 mm 行每行 22 个整数 x,yx,y,之间用一个空格隔开,表示有一条边从点 xx 指向点yy。

最后一行有两个用一个空格隔开的整数 s, ts,t,表示起点为 ss,终点为 tt。

输出格式:

输出只有一行,包含一个整数,表示满足题目描述的最短路径的长度。如果这样的路径不存在,输出-1−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
分析:题目要找出路径上的所有点的出边所指向的点都直接或间接与终点连通。也就是说当前点有一条边的出边最终没有连到终点,那么这个点就是不合条件的,标记不能通过这个点进行松弛。如样例2

因为2的一条出边指向6,而6最终没有指向终点5,所以与2有关的边不能作为松弛的点

#include<bits/stdc++.h>
using namespace std;
const int N = 1e6+10;
const int inf = 0x3f3f3f3f;
struct node{
    int v, w, nxt;
}edge[N];
int n, m, cnt, st, ed;
int fir[N], x[N], y[N], dis[N];
bool vis[N], book[N], book1[N];
inline void add(int u, int v, int w){
    edge[cnt] = (node){v, w, fir[u]};
    fir[u] = cnt++;
}
inline void dfs(int u){
    book[u] = true;
    for(int i = fir[u]; i; i = edge[i].nxt){
        int v = edge[i].v;
        if(!book[v])
            dfs(v);
    }
}
inline int spfa(int st){
    memset(vis, false, sizeof(vis));
    vis[st] = true;
    for(int  i = 1; i <= n; i++){
        dis[i] = inf;
    }
    dis[st] = 0;
    queue<int> Q;
    Q.push(st);
    while(!Q.empty()){
        int u = Q.front();
        Q.pop();
        vis[u] = true;
        for(int i = fir[u]; i; i = edge[i].nxt){
            int v = edge[i].v;
            if(book1[v]){
                continue;
            }
            if(dis[v] > dis[u] + edge[i].w){
                dis[v] = dis[u] + edge[i].w;
                if(!vis[v]){
                    vis[v] = false;
                    Q.push(v);
                }
            }
        }
    }
    return dis[ed];
}
int main(){
    #ifdef ONLINE_JUDGE
    #else
        freopen("in.txt", "r", stdin);
    #endif // ONLINE_JUDGE

    while(~scanf("%d%d", &n, &m)){
        cnt = 1;
        memset(fir, 0, sizeof(fir));
        memset(book, 0, sizeof(book));
        for(int i = 0; i < m; i++){
            scanf("%d%d", &x[i], &y[i]);
            add(y[i], x[i], 1);
        }
        scanf("%d%d", &st, &ed);
        dfs(ed);
        memset(fir, 0, sizeof(fir));
        for(int i = 0; i < m; i++){
            add(x[i], y[i], 1);
        }
        for(int i = 1; i <= n; i++){
            book1[i] = false;
            for(int j = fir[i]; j; j = edge[j].nxt){
                int v = edge[j].v;
                if(!book[v]){
                    book1[i] = true;
                    break;
                }
            }
        }
        int ans = spfa(st);
        if(ans == inf)
            printf("-1\n");
        else
            printf("%d\n", ans);
    }
    return 0;
}

posted on 2018-12-12 14:31  坤sir  阅读(158)  评论(0编辑  收藏  举报

导航