最短路 || UOJ 19 寻找道路

本文介绍了一种解决特定最短路径问题的方法,即在有向图中找到从起点到终点的最短路径,路径上的所有点的出边所指向的点都直接或间接与终点连通。通过反向建立图并使用BFS和SPFA算法来解决问题。
UOJ j19 寻找道路
在有向图G中,每条边的长度均为 1,现给定起点和终点,请你在图中找一条从起点到终点的最短路径,该路径满足以下条件:
路径上的所有点的出边所指向的点都直接或间接与终点连通。
*解法:反着建图,从终点bfs找能到达的点标记
在找一遍所有点中 如果某个点的入度点没做过标记 那么这个点就要被刨除
剩下的点中找最短路
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
#define S 200005
#define INF 1e9+10
int head[S], nxt[S], l[S], tot = 0, vis[S], flag[S], use[S], dist[S];
void build(int f, int t)
{
    l[++tot] = t;
    nxt[tot] = head[f];
    head[f] = tot;
}
queue<int> q;
void bfs(int s)
{
    vis[s] = 1;
    q.push(s);
    while(!q.empty())
    {
        int u = q.front(); q.pop();
        for(int i = head[u];i;i = nxt[i])
        {
            //注意这里的i指的是边,l[i]指的是点
            int v = l[i];
            if(!vis[v])
                vis[v] = 1, q.push(v);
        }
    }
}
int spfa(int s, int e)
{
    while(!q.empty()) q.pop();
    dist[s] = 0;
    use[s] = 1;
    q.push(s);
    while(!q.empty())
    {
        int u = q.front(); q.pop();
        use[u] = 0;
        for(int i = head[u];i;i = nxt[i])
        {
            int v = l[i];
            if(flag[v]) continue;
            if(dist[v] > dist[u] + 1)
            {
                dist[v] = dist[u] + 1;
                if(!use[v])
                    use[v] = 1, q.push(v);
            }
        }
    }
    return dist[e];
}
int main()
{
    int n, m, x, y, s, e;
    scanf("%d %d", &n, &m);
    for(int i = 1; i <= n; i++) dist[i] = INF;
    for(int i = 0; i < m; i++)
    {
        scanf("%d %d", &x, &y);
        build(y, x);
    }
    scanf("%d %d", &s, &e);
    bfs(e);
    for(int i = 1; i <= n; i++)
    {
        if(vis[i]) continue;
        for(int j = head[i];j;j = nxt[j]) //注意这里的j指的是边,l[j]指的是点
            flag[l[j]] = 1;
    }
    int dis = spfa(e, s);
    if(dis == INF) dis = -1;
    printf("%d\n", dis);
    return 0;
}

 

转载于:https://www.cnblogs.com/pinkglightning/p/8404719.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值