洛谷P2296 寻找道路(NOIP 2014)

题目描述 https://www.luogu.org/problemnew/show/P2296

这道题有个坑,虽然没掉进去,但是没跨过去
坑is here 路径上的所有点的出边所指向的点都直接或间接与终点连通。
所以就需要建反图 来删去一些没用的点
从终点倒着找 搜索不到的点就删去 与这些点直接相连的点也删去
要注意做标记的时候 要用一个新的数组 以防其他的被改变

还有就是数组模拟邻接表的应用

看代码吧

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int b[10050],q[2000050],st[10050],h[10050],f[10050],f2;
struct road
{
	int next,to;
};
road edge[2000050];
void bfs1(int x)
{
	int t=1,ha=1;
	q[t]=x; b[x]=0;
	while(ha<=t)
	{
	   x=q[ha];
	   for(int i=h[x];i>0;i=edge[i].next)
	     if(b[edge[i].to]==1)
	     {
	     	t++;
	     	q[t]=edge[i].to;
	     	b[edge[i].to]=0;
	     }
	   ha++;
	}
}
void bfs2(int x,int y)
{
	int t=1,ha=1;
	memset(q,0,sizeof(q));
	q[t]=x;
	while(ha<=t)
	{
	   x=q[ha];
	   for(int i=h[x];i>0;i=edge[i].next)
	     if(b[edge[i].to]==0)
	     {
	     	t++;
	     	q[t]=edge[i].to;
	     	st[t]=st[ha]+1;
	     	if(q[t]==y){ cout<<st[t]; f2=1; return;}
	     	b[edge[i].to]=1;
	     }
	   ha++;
	}
}
int main()
{  int x,y,i,j,n,m,s,t;
   
   freopen("road.in","r",stdin);
   freopen("road.out","w",stdout);
   cin>>n>>m;
   for(i=1;i<=n;i++) b[i]=1;
   for(i=1;i<=m;i++)
   {
   	  cin>>x>>y;
   	  edge[i].next=h[y];
   	  edge[i].to=x; h[y]=i;
   }
   cin>>s>>t; bfs1(t);//找到从终点能遍历的点
   for(i=1;i<=n;i++)
     if(b[i]==1)
       for(j=h[i];j>0;j=edge[j].next)
         f[edge[j].to]=1;//找到与删去的点直接相连的点
   for(i=1;i<=n;i++)
     if(b[i]==0&&f[i]==1)
       b[i]=1;//结合两个标记
   bfs2(t,s);//从终点开始找最短路径
   if(f2==0) cout<<"-1";
   
   fclose(stdin); fclose(stdout);
  return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_42920122/article/details/82950836