在有向图 G 中,每条边的长度均为 1,现给定起点和终点,请你在图中找一条从起点到 终点的路径,该路径满足以下条件:
- 路径上的所有点的出边所指向的点都直接或间接与终点连通。
- 在满足条件 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 }