[NOIP2014]寻找道路

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[NOIP2014]寻找道路相关的知识,希望对你有一定的参考价值。

描述

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

  1. 路径上的所有点的出边所指向的点都直接或间接与终点连通。
  2. 在满足条件 1 的情况下使路径最短。

注意:图 G 中可能存在重边和自环,题目保证终点没有出边。 请你输出符合条件的路径的长度。

格式

输入格式

第一行有两个用一个空格隔开的整数 n 和 m,表示图有 n 个点和 m 条边。

接下来的 m 行每行 2 个整数 x、y,之间用一个空格隔开,表示有一条边从点 x 指向点y。

最后一行有两个用一个空格隔开的整数 s、t,表示起点为 s,终点为 t。

输出格式

输出只有一行,包含一个整数,表示满足题目描述的最短路径的长度。

如果这样的路径不存在,输出-1。

样例1

样例输入1[复制]

 
3 2
1 2
2 1
1 3

样例输出1[复制]

 
-1

样例2

样例输入2[复制]

 
6 6
1 2
1 3
2 6
2 5
4 5
3 4
1 5

样例输出2[复制]

 
3

限制

对于 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]寻找道路的主要内容,如果未能解决你的问题,请参考以下文章

寻找道路(NOIP2014)神奇之题。。

[NOIP2014]寻找道路

[NOIP2014] 寻找道路

[NOIP2014]寻找道路 题解

NOIP TG 2014 寻找道路

[NOIP2014] 提高组 洛谷P2296 寻找道路