题目大意:给定一个有向图,找到一条满足路径上的所有点的出边所指向的点都直接或间接与终点连通条件的最短路径。
方法:dfs+SPFA
首先,我们需要判断图上哪些点可以走,哪些点不可以走。
我们对于每一个边建一个边权为-1的反向边,从终点开始dfs,这样一来我们就可以知道那些点与终点相连了。
接着,我们枚举每一个点,枚举他的每一条出边,如果都能到终点,就代表这个点可以走
然后,我们跑一遍SPFA求最短路即可(注意判断只能走标记能走的点)
时间复杂度:O(vn)最慢的也就是SPFA了,但是本题数据小,还是能过去的。
最后,附上本题代码:
1 #include<cstdio> 2 #include<algorithm> 3 #include<cmath> 4 #include<cstring> 5 #include<iostream> 6 #include<queue> 7 using namespace std; 8 //Debug Yufenglin 9 #define dej printf("Running\n"); 10 #define dep1(x) cout<<#x<<"="<<x<<endl; 11 #define dep2(x,y) cout<<#x<<"="<<x<<' '<<#y<<"="<<y<<endl; 12 #define dep3(x,y,z) cout<<#x<<"="<<x<<' '<<#y<<"="<<y<<' '<<#z<<"="<<z<<endl; 13 14 //Standfor Yufenglin 15 #define LL long long 16 #define LB long double 17 #define reg register 18 #define il inline 19 #define maxn 10000 20 #define maxm 200000 21 #define inf 1000000000 22 23 int n,m,cnt,s,t; 24 struct EDGE 25 { 26 int to,nxt,v; 27 }; 28 EDGE edge[maxm*2+5]; 29 bool canvis[maxn+5],vis[maxn+5],visited[maxn+5]; 30 int dis[maxn+5],head[maxn+5]; 31 queue<int>q; 32 33 void add(int x,int y,int z) 34 { 35 edge[++cnt].to=y; 36 edge[cnt].v=z; 37 edge[cnt].nxt=head[x]; 38 head[x]=cnt; 39 } 40 void dfs(int x) 41 { 42 //canvis[x]=1; 43 for(int i=head[x]; i; i=edge[i].nxt) 44 { 45 if(edge[i].v==-1&&canvis[edge[i].to]==0) 46 { 47 canvis[edge[i].to] = 1; 48 dfs(edge[i].to); 49 } 50 } 51 } 52 void SPFA() 53 { 54 for(int i=1; i<=n; i++) 55 { 56 dis[i]=inf; 57 } 58 int u=s; 59 dis[u]=0; 60 vis[u]=1; 61 q.push(u); 62 while(!q.empty()) 63 { 64 u=q.front(); 65 vis[u]=0; 66 q.pop(); 67 for(int i=head[u]; i; i=edge[i].nxt) 68 { 69 if(visited[edge[i].to]==0) continue; 70 if(dis[edge[i].to]>dis[u]+1) 71 { 72 dis[edge[i].to]=dis[u]+1; 73 if(vis[edge[i].to]==0) 74 { 75 vis[edge[i].to]=1; 76 q.push(edge[i].to); 77 } 78 } 79 } 80 } 81 } 82 int main() 83 { 84 scanf("%d%d",&n,&m); 85 for(int i=1; i<=m; i++) 86 { 87 int x,y; 88 scanf("%d%d",&x,&y); 89 if(x==y) continue; 90 add(x,y,1); 91 add(y,x,-1); 92 } 93 scanf("%d%d",&s,&t); 94 canvis[t] = 1; 95 dfs(t); 96 for(int i=1; i<=n; i++) 97 { 98 bool flag=1; 99 for(int j=head[i];j;j=edge[j].nxt) 100 { 101 if(canvis[edge[j].to]==0) 102 { 103 flag=0; 104 break; 105 } 106 } 107 if(flag==1) visited[i]=1; 108 } 109 SPFA(); 110 if(dis[t]==inf) printf("-1\n"); 111 else printf("%d\n",dis[t]); 112 return 0; 113 }