[NOIP2014]寻找道路
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[NOIP2014]寻找道路相关的知识,希望对你有一定的参考价值。
描述
在有向图 G 中,每条边的长度均为 1,现给定起点和终点,请你在图中找一条从起点到 终点的路径,该路径满足以下条件:
- 路径上的所有点的出边所指向的点都直接或间接与终点连通。
- 在满足条件 1 的情况下使路径最短。
注意:图 G 中可能存在重边和自环,题目保证终点没有出边。 请你输出符合条件的路径的长度。
格式
输入格式
第一行有两个用一个空格隔开的整数 n 和 m,表示图有 n 个点和 m 条边。
接下来的 m 行每行 2 个整数 x、y,之间用一个空格隔开,表示有一条边从点 x 指向点y。
最后一行有两个用一个空格隔开的整数 s、t,表示起点为 s,终点为 t。
输出格式
输出只有一行,包含一个整数,表示满足题目描述的最短路径的长度。
如果这样的路径不存在,输出-1。
限制
对于 30%的数据,0 < n ≤ 10,0 < m ≤ 20;
对于 60%的数据,0 < n ≤ 100,0 < m ≤ 2000;
对于 100%的数据,0 < n ≤ 10,000,0 < m ≤ 200,000,0 < x,y,s,t ≤ n,x ≠ t。
提示
【输入输出样例1说明】
如上图所示,箭头表示有向道路,圆点表示城市。起点 1 与终点 3 不连通,所以满足题目描述的路径不存在,故输出-1。
【输入输出样例2说明】
如上图所示,满足条件的路径为 1->3->4->5。注意点 2 不能在答案路径中,因为点 2 连了一条边到点 6,而点 6 不与终点 5 连通。
来源
NOIP2014 提高组 Day2
分析
一开始我想的是顺着用dfs先去找符合要求的点,再求一次sssp。但后来发现正着搜索很难处理有环的情况。后来看了一些神犇的题解(他们都无一例外写着“这是一道水题”),发现是要先反着来一次dfs找到可以与终点相同的节点,然后再根据题意删掉那些不符合要求的点(我就是因为没审清楚题目哪些点要去掉,调试了一下午),最后正着一遍bfs就可以找到最短路径了。至于没有路的情况只要bfs加个判断就可以了。
另外到了这种几十万级别的数据下大家还是少用iostream比较好,经常容易被坑......
代码
1 #include <cstdio> 2 #include <vector> 3 #include <queue> 4 using namespace std; 5 vector<int> U[10001]; 6 vector<int> V[10001]; 7 vector<int> F; 8 bool B[10001]; 9 bool I[10001]; 10 int m, n, s, t, ans; 11 void dfs(int i) 12 { 13 B[i] = true; 14 for (int j = 0; j != V[i].size(); ++j) 15 if (!B[V[i][j]]) 16 dfs(V[i][j]); 17 } 18 void clean(int i) 19 { 20 if (!B[i]) { 21 for (int j = 0; j != V[i].size(); ++j) { 22 if (B[V[i][j]]) { 23 F.push_back(V[i][j]); 24 } 25 } 26 } 27 } 28 void bfs() 29 { 30 queue<int> Q; 31 queue<int> L; 32 Q.push(s); 33 L.push(0); 34 I[s] = true; 35 bool flag = true; 36 while (!Q.empty() && flag) { 37 int k = Q.front(); 38 int l = L.front(); 39 Q.pop(); 40 L.pop(); 41 if (k == t) { 42 ans = l; 43 flag = false; 44 } 45 for (int i = 0; i != U[k].size() && flag; ++i) { 46 if (B[U[k][i]] && (!I[U[k][i]])) { 47 I[U[k][i]] = true; 48 Q.push(U[k][i]); 49 L.push(l + 1); 50 } 51 } 52 } 53 if (flag) 54 ans = -1; 55 } 56 int main() 57 { 58 scanf("%d%d", &n, &m); 59 for (int i = 0, u, v; i != m; ++i) { 60 scanf("%d%d", &u, &v); 61 U[u].push_back(v); 62 V[v].push_back(u); 63 } 64 scanf("%d%d", &s, &t); 65 dfs(t); 66 if (!B[s]) 67 ans = -1; 68 if (ans == 0) { 69 for (int i = 1; i <= n; ++i) 70 clean(i); 71 for (int i = 0; i != F.size(); ++i) 72 B[F[i]] = false; 73 B[s] = true; 74 bfs(); 75 } 76 printf("%d", ans); 77 return 0; 78 }
以上是关于[NOIP2014]寻找道路的主要内容,如果未能解决你的问题,请参考以下文章