- 题库 :洛谷
- 题号 :2296
- 题目 :寻找道路
- link :https://www.luogu.com.cn/problem/P2296
思路 :首先既然要满足第一个条件,我们可以建反向边,从起点出发走反向边,标记所能到达的点。没有被标记过的点就把他的父亲(谁到它的点)和它本身给标记为不可到达,然后就求最短路,如果碰到标记为不可到达的点,就continue,最后dis[e]就是答案。
代码 :
1 #include <bits/stdc++.h> 2 #define INF 0x3f3f3f3f 3 using namespace std; 4 int n, m, head[10001], head1[10001], dis[10001], vis[10001], no[10001], mark[10001], num, num1, s, e; 5 struct node 6 { 7 int next, to, val; 8 }stu[200001], stu1[200001]; 9 inline void add(int x, int y, int z)//正向边 10 { 11 stu[++num].next = head[x]; 12 stu[num].to = y; 13 stu[num].val = z; 14 head[x] = num; 15 return; 16 } 17 inline void add1(int x, int y, int z)//反向边 18 { 19 stu1[++num1].next = head1[x]; 20 stu1[num1].to = y; 21 stu1[num1].val = z; 22 head1[x] = num1; 23 return; 24 } 25 inline void dfs(int u)//从终点dfs搜索能到达的点 26 { 27 for(register int i = head1[u]; i; i = stu1[i].next) 28 { 29 int k = stu1[i].to; 30 if(!mark[k]) 31 { 32 mark[k] = 1; 33 dfs(k); 34 } 35 } 36 return; 37 } 38 inline void spfa(int s)//求最短路 39 { 40 queue < int > pru; 41 memset(vis, 0, sizeof(vis)); 42 memset(dis, INF, sizeof(dis)); 43 dis[s] = 0; 44 vis[s] = 1; 45 pru.push(s); 46 while(!pru.empty()) 47 { 48 int u = pru.front(); 49 pru.pop(); 50 vis[u] = 0; 51 for(register int i = head[u]; i; i = stu[i].next) 52 { 53 int k = stu[i].to; 54 if(no[k])//如果不可以走(不满足条件1) 55 { 56 continue; 57 } 58 if(dis[k] > dis[u] + stu[i].val) 59 { 60 dis[k] = dis[u] + stu[i].val; 61 if(!vis[k]) 62 { 63 vis[k] = 1; 64 pru.push(k); 65 } 66 } 67 } 68 } 69 return; 70 } 71 signed main() 72 { 73 scanf("%d %d", &n, &m); 74 for(register int i = 1, x, y; i <= m; ++i) 75 { 76 scanf("%d %d", &x, &y); 77 add(x, y, 1); 78 add1(y, x, 1); 79 } 80 scanf("%d %d", &s, &e); 81 dfs(e); 82 mark[e] = 1;//记得把终点标记为搜到了 83 for(register int u = 1; u <= n; ++u)//搜索所有点 84 { 85 if(!mark[u])//没被标记的 86 { 87 no[u] = 1;//不能走 88 for(register int i = head1[u]; i; i = stu1[i].next)//他的父亲也不能走 89 { 90 int k = stu1[i].to; 91 no[k] = 1; 92 } 93 } 94 } 95 spfa(s); 96 printf(dis[e] == INF ? "-1" : "%d", dis[e]); 97 return 0; 98 }