[题目链接]
[算法]
首先,在反向图上从终点广搜,求出每个点是否可以在答案路径中
然后在正向图中求出源点至终点的最短路,同样可以使用广搜
时间复杂度 : O(N)
[代码]
#include<bits/stdc++.h> using namespace std; #define MAXN 10010 #define MAXM 200010 struct edge { int to,nxt; } e[MAXM << 1]; int i,n,m,u,v,s,t,tot; int head[MAXN],rhead[MAXN],deg[MAXN]; bool flag[MAXN]; namespace IO { template <typename T> inline void read(T &x) { int f = 1; x = 0; char c = getchar(); for (; !isdigit(c); c = getchar()) { if (c == '-') f = -f; } for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0'; x *= f; } template <typename T> inline void write(T x) { if (x < 0) { putchar('-'); x = -x; } if (x > 9) write(x / 10); putchar(x % 10 + '0'); } template <typename T> inline void writeln(T x) { write(x); puts(""); } } ; inline void addedge(int u,int v) { tot++; e[tot] = (edge){v,head[u]}; head[u] = tot; } inline void addredge(int u,int v) { tot++; e[tot] = (edge){v,rhead[u]}; rhead[u] = tot; } inline void bfs1(int s) { int i,u,v,l,r; static int q[MAXN],cnt[MAXN]; static bool visited[MAXN]; for (i = 1; i <= n; i++) cnt[i] = 0; q[l = r = 1] = s; flag[s] = true; while (l <= r) { u = q[l]; l++; for (i = rhead[u]; i; i = e[i].nxt) { v = e[i].to; if (!visited[v]) { visited[v] = true; q[++r] = v; } cnt[v]++; } } for (i = 1; i <= n; i++) flag[i] = (cnt[i] == deg[i]); } inline int bfs2(int s) { int i,u,v,l,r; static int q[MAXN],dist[MAXN]; static bool visited[MAXN]; if (!flag[s]) return -1; for (i = 1; i <= n; i++) visited[i] = false; q[l = r = 1] = s; dist[s] = 0; visited[s] = true; while (l <= r) { u = q[l]; l++; for (i = head[u]; i; i = e[i].nxt) { v = e[i].to; if (!visited[v] && flag[v]) { visited[v] = true; dist[v] = dist[u] + 1; q[++r] = v; } } } return dist[t] > 0 ? dist[t] : -1; } int main() { IO :: read(n); IO :: read(m); for (i = 1; i <= m; i++) { IO :: read(u); IO :: read(v); addedge(u,v); addredge(v,u); deg[u]++; } IO :: read(s); IO :: read(t); bfs1(t); IO :: writeln(bfs2(s)); return 0; }