洛谷P2296 寻找道路

\(\Large\textbf{Description:} \large {在有向图 G 中,每条边的长度均为 1,现给定起点和终点,请你在图中找一条从起点到终点的路径,该路径满足以下条件:}\)

\(\large {1.路径上的所有点的出边所指向的点都直接或间接与终点连通。}\)

\(\large {2.在满足条件11的情况下使路径最短。}\)

\(\Large\textbf{Solution:} \large {考虑反向建边,然后从终点开始遍历一遍图,把符合条件的点打上标记,再从终点开始跑一边bfs即可。}\)

\(\Large\textbf{Code:}\)

#include 
#include 
#include 
#define LL long long
#define gc() getchar()
#define rep(i, a, b) for (int i = (a); i <= (b); ++i)
using namespace std;
const int N = 2e5 + 5;
int n, m, cnt, s, t, ans, in[10005], head[10005], vis[1005], f[10005];

struct Edge {
    int to, next;   
}e[N << 1];

struct Node {
    int num, dis;   
};
queue q;

inline int read() {
    char ch = gc();
    int ans = 0;
    while (ch > '9' || ch < '0') ch = gc();
    while (ch >= '0' && ch <= '9') ans = (ans << 1) + (ans << 3) + ch - '0', ch = gc();
    return ans; 
}

inline void add(int l, int r) {
    e[++cnt].to = r;
    e[cnt].next = head[l];
    head[l] = cnt;  
}

inline void dfs(int now) {
    f[now] = 1;
    for (int i = head[now]; i ; i = e[i].next) {
        int u = e[i].to;
        ++vis[u];
        if (f[u]) continue;
        dfs(u);
    }
}

int main() {
    n = read(), m = read();
    int l, r;
    rep(i, 1, m) l = read(), r = read(), add(r, l), ++in[l];
    s = read(), t = read();
    dfs(t);
    rep(i, 1, n) { f[i] = 0; if (in[i] == vis[i]) f[i] = 1; in[i] = 0; }
    q.push((Node){t, 0});
    while (!q.empty()) {
        Node x = q.front();
        q.pop();
        for (int i = head[x.num]; i ; i = e[i].next) {
            int u = e[i].to;
            if (in[u] || !f[u]) continue;
            if (u == s) { printf("%d\n", x.dis + 1); return 0; }
            else q.push((Node){u, x.dis + 1});
        }
    }
    printf("-1\n");
    return 0;
} 

\(\large\color{pink}{by\quad Miraclys}\)

你可能感兴趣的:(洛谷P2296 寻找道路)