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 ", dis); return 0; }