P2296 寻找道路
题目描述
在有向图 \(G\) 中,每条边的长度均为 \(1\) ,现给定起点和终点,请你在图中找一条从起点到终点的路径,该路径满足以下条件:
- 路径上的所有点的出边所指向的点都直接或间接与终点连通。
- 在满足上一个条件的情况下使路径最短。
注意:图 \(G\) 中可能存在重边和自环,题目保证终点没有出边。
请你输出符合条件的路径的长度。
这一道算是一个模板的变形吧
我们现将能够到达终点的点判断出来。
然后从中选出所指向的点都能到达终点的点
最后跑一个bfs就行了(前面几个不都是跑bfs么!!!)
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<queue>
using std::queue;
const int max_M=201000;
const int max_N=11000;
int n,m,s,t;
struct node
{
int point;
int nxt;
};
node line[max_M],Line[max_M];
int head[max_N],Head[max_N],tail,Tail;
void add(int a,int b)
{
line[++tail].point=b;
line[tail].nxt=head[a];
head[a]=tail;
Line[++Tail].point=a;
Line[Tail].nxt=Head[b];
Head[b]=Tail;
}
bool reach[max_N];
bool use[max_N];
void R_bfs(int start)
{
reach[start]=true;
queue<int>q;
q.push(start);
while(!q.empty())
{
int now=q.front();q.pop();
for(int i=Head[now];i;i=Line[i].nxt)
if(!reach[Line[i].point])
{
reach[Line[i].point]=true;
q.push(Line[i].point);
}
}
for(int i=1;i<=n;i++)
{
use[i]=true;
for(int j=head[i];j;j=line[j].nxt)
if(!reach[line[j].point])
{
use[i]=false;
break;
}
if(!head[i]) use[i]=false;
}
}
int ans;
int dis[max_N];
void bfs(int start)
{
if(!reach[t])
{
ans=-1;
return ;
}
use[t]=true;
for(int i=1;i<=n;i++) dis[i]=0x7fffffff;
dis[start]=0;
queue<int>q;
q.push(start);
while(!q.empty())
{
int now=q.front();
q.pop();
for(int i=head[now];i;i=line[i].nxt)
if(dis[line[i].point]>dis[now]+1&&use[line[i].point])
{
dis[line[i].point]=dis[now]+1;
q.push(line[i].point);
}
}
ans=dis[t] == 0x7fffffff ? -1 : dis[t] ;
return ;
}
int main()
{
scanf("%d%d",&n,&m);
int a,b;
for(int i=1;i<=m;i++)
{
scanf("%d%d",&a,&b);
add(a,b);
}
scanf("%d%d",&s,&t);
R_bfs(t);
bfs(s);
printf("%d",ans);
}