寻找道路 vijos1909 NOIP2014 D2T2 SPFA

Posted JayWang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了寻找道路 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

 

以上是关于寻找道路 vijos1909 NOIP2014 D2T2 SPFA的主要内容,如果未能解决你的问题,请参考以下文章

DFS图论NOIP2014寻找道路

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

[NOIP2014]寻找道路

[NOIP2014] 寻找道路

[NOIP2014]寻找道路 题解

NOIP TG 2014 寻找道路