• 寻找道路 vijos1909 NOIP2014 D2T2 SPFA


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

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

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

    我们存两个图,一个是原图,一个是把原图的边反向后的【反向图】。

    我们先用反向图,以目标终点t为起点跑一遍spfa,然后把能跑到的点都记录下来,留待后用。

    然后再用正向图(原图),以目标起点s为起点再跑一遍spfa,注意在跑的时候不要跑不满足要求的点

    我们用check函数来检验某个点是否符合要求,代码如下。其中able属性是是否在第一次spfa中标记过,若标记过,则为true。

    inline bool check(int u)
    {
        if(!able[u]) return false;
        for (register int i=head[u];i;i=w[i].next)
            if(!able[w[i].to]) return false;
        return true;
    }

    附上AC代码

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 #include<cmath>
      5 #include<queue>
      6 #include<iostream>
      7 using namespace std;
      8 template<class T> inline void read(T &_a){
      9     bool f=0;int _ch=getchar();_a=0;
     10     while(_ch<'0' || _ch>'9'){if(_ch=='-')f=1;_ch=getchar();}
     11     while(_ch>='0' && _ch<='9'){_a=(_a<<1)+(_a<<3)+_ch-'0';_ch=getchar();}
     12     if(f)_a=-_a;
     13 }
     14 
     15 const int maxn=10001,maxm=200001;
     16 struct edge
     17 {
     18     int to,next;
     19 }w[maxm],w2[maxm];
     20 int n,m,egcnt,egcnt2,head[maxn],head2[maxn],s,t,dis2[maxn],dis[maxn];
     21 queue<int>q;
     22 bool ins[maxn],able[maxn];
     23 
     24 inline void addedge(int from,int to)
     25 {
     26     w[++egcnt].to=to;
     27     w[egcnt].next=head[from];
     28     head[from]=egcnt;
     29     w2[++egcnt2].to=from;
     30     w2[egcnt2].next=head2[to];
     31     head2[to]=egcnt2;
     32 }
     33 
     34 inline void spfa2()
     35 {
     36     q.push(t);
     37     memset(dis2,0x7f,sizeof(dis2));
     38     dis2[t]=0;
     39     while(!q.empty())
     40     {
     41         int now=q.front(); q.pop();
     42         ins[now]=false;
     43         for (register int i=head2[now];i;i=w2[i].next)
     44         {
     45             if(dis2[w2[i].to]>dis2[now]+1)
     46             {
     47                 dis2[w2[i].to]=dis2[now]+1;
     48                 if(!ins[w2[i].to])
     49                 {
     50                     q.push(w2[i].to);
     51                     ins[w2[i].to]=true;
     52                 }
     53             }
     54         }
     55     }
     56 }
     57 
     58 inline bool check(int u)
     59 {
     60     if(!able[u]) return false;
     61     for (register int i=head[u];i;i=w[i].next)
     62         if(!able[w[i].to]) return false;
     63     return true;
     64 }
     65 
     66 inline void spfa()
     67 {
     68     while(!q.empty()) q.pop();
     69     memset(ins,0,sizeof(ins));
     70     q.push(s);
     71     memset(dis,0x7f,sizeof(dis));
     72     dis[s]=0;
     73     while(!q.empty())
     74     {
     75         int now=q.front(); q.pop();
     76         ins[now]=false;
     77         for (register int i=head[now];i;i=w[i].next)
     78             if(check(w[i].to)){
     79             if(dis[w[i].to]>dis[now]+1)
     80             {
     81                 dis[w[i].to]=dis[now]+1;
     82                 if(!ins[w[i].to])
     83                 {
     84                     q.push(w[i].to);
     85                     ins[w[i].to]=true;
     86                 }
     87             }
     88         }
     89     }
     90 }
     91 
     92 int main()
     93 {
     94     read(n); read(m);
     95     for (register int i=1,x,y;i<=m;++i) read(x),read(y),addedge(x,y);
     96     read(s); read(t);
     97     spfa2();
     98     for (register int i=1;i<=n;++i) if(dis2[i]<=n) able[i]=true;
     99     spfa();
    100     printf("%d",dis[t]>n?-1:dis[t]);
    101     return 0;
    102 }
    View Code
  • 相关阅读:
    《网络攻防》实验八:Web基础
    《网络攻防》实验七:网络欺诈技术防范
    《网络攻防》实验六:信息搜集与漏洞扫描
    《网络攻防》实验五:MSF基础应用
    《网络攻防》实验四:恶意代码分析
    《网络攻防》实验三:免杀原理与实践
    《网络攻防》实验二:后门原理与实践
    20145213《网络对抗》逆向及Bof基础
    《课程设计》——cupp的使用
    《课程设计》——foremost的使用
  • 原文地址:https://www.cnblogs.com/jaywang/p/7745433.html
Copyright © 2020-2023  润新知