luoguP2296 寻找道路

因为是出边与终点直接或间接相连,所以将边反向,从终边开始,将所有终边能到达的点都打上标记
因为是最短路,所以不需要处理重边和自环,于是再跑最短路就好
题目关键:
路径上的所有点的出边所指向的点都直接或间接与终点连通

这句话的意识也就是变相的告诉我们,对于一个点x, 他的一条出边连的点y并不能直接或间接的与终点相连,此时我们要给x打上标记
因此,我们在最初从终点开始扫的仅仅是终点能到达的,对于终点不能到达的,我们最后要单独把他们的父节点(方便理解的说法)安排上
但是如果只使用一个标记数组,会出现后效性,所以我们要使用两个标记数组

处理完后跑最短路即可

 

此题学会的操作:在特定时候,为了简化问题,可以将边反向

此题踩到的雷:kill是关键词,然后吃了两发ce(本来可以1A)

 1 #include<bits/stdc++.h>
 2 #define uint unsigned int
 3 using namespace std;
 4 const int maxm = 200086;
 5 const int maxn = 10086;
 6 struct shiki {
 7     int y, net;
 8 }e[maxm];
 9 int lin[maxm], len = 0;
10 int n, m, flag;
11 int s, t; 
12 bool kil[maxn], vis[maxn];
13 int dis[maxn];
14 
15 inline int read() {
16     int x = 0, y = 1;
17     char ch = getchar();
18     while(!isdigit(ch)) {
19         if(ch == '-') y = -1;
20         ch = getchar();
21     }
22     while(isdigit(ch)) {
23         x = (x << 1) + (x << 3) + ch - '0';
24         ch = getchar();
25     }
26     return x * y;
27 }
28 
29 inline void insert(int xx, int yy) {
30     e[++len].net = lin[xx];
31     e[len].y = yy;
32     lin[xx] = len;
33 }
34 
35 void find_your_brother(int t) {
36     vis[t] = kil[t] = 1;
37     for(int i = lin[t]; i; i = e[i].net) 
38         if(!vis[e[i].y]) find_your_brother(e[i].y);
39 }
40 
41 queue<int> q;
42 inline void spfa(int st) {
43     memset(vis, 0, sizeof(vis));
44     memset(dis, 0x3f3f3f, sizeof(dis));
45     flag = dis[0];
46     q.push(st); vis[st] = 0, dis[st] = 0;
47     while(!q.empty()) {
48         int k = q.front(); q.pop();
49         vis[k] = 0;
50         for(int i = lin[k]; i; i = e[i].net) {
51             int to = e[i].y;
52             if(!kil[to]) continue;
53             if(dis[to] > dis[k] + 1) {
54                 dis[to] = dis[k] + 1;
55                 if(!vis[to]) {
56                     vis[to] = 1;
57                     q.push(to);
58                 }
59             }
60         }
61     }
62 }
63 
64 int main() {
65     n = read(), m = read();
66     for(int i = 1; i <= m; ++i) {
67         int x, y;
68         x = read(), y = read();
69         insert(y, x);//反向建边 
70     }
71     s = read(), t = read();
72     find_your_brother(t);
73     for(register uint i = 1; i <= n; ++i) {
74         if(!vis[i])
75             for(int j = lin[i]; j; j = e[j].net) 
76                 if(kil[e[j].y]) kil[e[j].y] = 0;
77     }
78     spfa(t);
79     if(dis[s] >= flag) cout << -1 << '\n';
80     else cout << dis[s] << '\n';
81     return 0;
82 }

 

posted @ 2018-08-14 20:40  YuWenjue  阅读(184)  评论(0编辑  收藏  举报