【bf】洛谷 P2296 寻找道路 暴力

一、题目:

洛谷原题

二、思路:

这是暴力做法,正解请看下一篇
floyd(传递闭包)+ SPFA。
用传递闭包标记哪些点和终点联通,然后跑SPFA,在判断点是否入队是增加一条判断条件——是否与终点连通。

Tips:在这道题中,SPFA的实质是BFS,我习惯叫它为SPFA。

注意起点的特判。
得分:60分。

三、代码:

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>

using namespace std;
inline int read(void) {
    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 f * x;
}

const int maxn = 10005, maxm = 200005;

int n, m, head[maxn], tot, start, en, dis[maxn], flag[maxn][maxn];
bool vis[maxn];


struct Edge {
    int y, next;
}e[maxm];

inline void connect(int x, int y) {
    e[++tot].y = y; e[tot].next = head[x]; head[x] = tot;
}

inline bool check(int node) {
    for (register int i = head[node]; i; i = e[i].next) {
        if (!flag[e[i].y][en])return false;
    }
    return true;
}

inline void init(void) {
    n = read(); m = read();
    for (register int i = 1; i <= m; i++) {
        int x = read(), y = read();
        if (x == y)continue;
        if (flag[x][y])continue;
        flag[x][y] = true;
        connect(x, y);
    }
    start = read(); en = read();
    for (register int i = 1; i <= n; i++)flag[i][i] = true;
    for (register int k = 1; k <= n; k++)
        for (register int i = 1; i <= n; i++)
            for (register int j = 1; j <= n; j++) 
                flag[i][j] |= (flag[i][k] && flag[k][j]);
}

inline void solve(void) {
    queue<int>q; q.push(start);
    vis[start] = true;
    memset(dis, 0x3f, sizeof(dis)); dis[start] = 0;
    while (q.size()) {
        int u = q.front(); q.pop(); vis[u] = false;
        for (register int i = head[u]; i; i = e[i].next) {
            int y = e[i].y;
            if (dis[y] > dis[u] + 1 && check(y)) {
                dis[y] = dis[u] + 1;
                if (!vis[y]) {
                    q.push(y); vis[y] = true;
                }
            }
        }
    }
    if (dis[en] == 0x3f3f3f3f) { puts("-1"); }
    else printf("%d\n", dis[en]);
}

int main()
{
    init();
    if (!flag[start][en]) { puts("-1"); return 0; }
    solve();
    return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值