比较裸的图论,结果自己还是没做出来,我真菜。
我们根据题意,只要把不能通向终点的点求出,然后再分别以这些点为起点,求出它们能到达的点,这些点也不能在路径上。
之后跑一个最短路即可。
注意以上操作均是在建反图的基础上进行的。我们交换起终点,这是等价的。
细节操作:开新数组记录不能到达的点,因为搜索还没结束,会重复。
Code
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include<cstdio> 2 #include<algorithm> 3 #include<queue> 4 5 using namespace std; 6 const int inf=0x3f3f3f3f; 7 8 int n,m,x,y,s,t,tot,qwq; 9 int head[10090],vis[10090],laz1[10090],dis[10090],tmp[10090],laz[10090]; 10 struct node{ 11 int to,next; 12 }edge[200090]; 13 14 void add(int x,int y) 15 { 16 edge[++tot].to=y; 17 edge[tot].next=head[x]; 18 head[x]=tot; 19 } 20 void dfs(int x) 21 { 22 laz1[x]=1; 23 for(int i=head[x];i;i=edge[i].next) 24 { 25 int y=edge[i].to; 26 if(laz1[y]) continue; 27 dfs(y); 28 } 29 } 30 31 void spfa() 32 { 33 queue<int>q; 34 for(int i=1;i<=n;i++) dis[i]=inf; 35 q.push(t);vis[t]=1;dis[t]=0; 36 while(!q.empty()) 37 { 38 int x=q.front();q.pop();vis[x]=0; 39 if(!laz[x]) continue; 40 for(int i=head[x];i;i=edge[i].next) 41 { 42 int y=edge[i].to; 43 if(dis[y]>dis[x]+1&&laz[y]) 44 { 45 dis[y]=dis[x]+1; 46 if(!vis[y]) q.push(y),vis[y]=1; 47 } 48 } 49 } 50 } 51 52 int main() 53 { 54 scanf("%d%d",&n,&m); 55 for(int i=1;i<=m;i++) 56 scanf("%d%d",&x,&y),add(y,x); 57 scanf("%d%d",&s,&t); 58 dfs(t); 59 if(!laz1[s]) 60 { 61 printf("-1"); 62 return 0; 63 } 64 for(int i=1;i<=n;i++) 65 { 66 if(!laz1[i]) 67 { 68 for(int k=head[i];k;k=edge[k].next) 69 tmp[++qwq]=edge[k].to; 70 } 71 else laz[i]=1; 72 } 73 for(int i=1;i<=qwq;i++) laz[tmp[i]]=0; 74 spfa(); 75 printf("%d",dis[s]); 76 return 0; 77 }