P2296 寻找道路

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);
}
posted @ 2018-07-27 16:17  Lance1ot  阅读(159)  评论(0编辑  收藏  举报