• 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 << '
    ';
    80     else cout << dis[s] << '
    ';
    81     return 0;
    82 }
  • 相关阅读:
    【C++】小心使用文件读写模式:回车(' ') 换行(' ')问题的一次纠结经历
    小记同学一次奇葩的DNS欺骗实验失败经历
    IE的BHO通过IHTMLDocument2接口获得网页源代码
    HTML5离线缓存攻击测试(二)
    HTML5离线缓存攻击测试
    PHP防止SQL注入的方法
    Linux系统环境变量的四个配置文件的关系
    CentOS 7 上搭建LNMP环境
    [Linux][Nginx][02]Config
    [Linux][Nginx][01]Install
  • 原文地址:https://www.cnblogs.com/ywjblog/p/9477747.html
Copyright © 2020-2023  润新知