NOIP2014day2T2————寻找道路(road)

还是你谷
我永远爱洛谷.jpg

解析

作为一道折磨了我至少三四个小时的题,其实也不难
首先分为两个部分
1.给不能走的点染色
2.最短路
最短路的话,因为边长都是一,所以其实用bfs就可以(然而我还是弱智的用了SPFA)
关键是染色,如果正着搜的话不好写,所以我们存一个反图,然后找终点能到达的位置
然后把他们标记为能走;
接下来第二次染色,不能走的点,明显和他直接相连的点也是不可以走的,将他们的标记改成不能走(这时候要注意不能直接一边找一边改原来的标志数组,要另设一个数组,找完之后再改原数组)
然后最短路,这时候要注意因为我们存的是反图,所以要从终点找去起点的最短路(二者是等价的)
最后要注意的是,数组模拟邻接表储存的时候,next和to都是存边的,要按边的规模来设
(我调试三四个小时的罪魁祸首QAQ)

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int MAXN=10003;
struct deliver{
	int next,to;
}a[200005];
int n,m,s,e;
int hd[MAXN],vis[MAXN],vv[MAXN],num1;
int h,t,dis[MAXN],fl[MAXN],que[2*MAXN+5];
inline void add(int u,int v)
{
	a[++num1].next=hd[u];
	a[num1].to=v;
	hd[u]=num1;
}
void dfs(int k)
{
 	vis[k]=1;
 	for(int i=hd[k];i;i=a[i].next)
 	  if(vis[a[i].to]==0) dfs(a[i].to);
}
int main()
{
	scanf("%d%d",&n,&m);
	int x1,y1;
	for(int i=1;i<=m;i++)
	{	
		scanf("%d%d",&x1,&y1);
		if(x1!=y1) add(y1,x1);
	}
	scanf("%d%d",&s,&e);
	
	dfs(e);//染色
	for(int i=1;i<=n;i++)
	  if(vis[i]==0)
	    for(int j=hd[i];j;j=a[j].next)
	      vv[a[j].to]=1;
	for(int i=1;i<=n;i++)
	  if(vv[i]==1) vis[i]=0;
	  
	for(int i=1;i<=n;i++)//最短路
	 dis[i]=0x7fffffff/3;
	dis[e]=0;fl[e]=1;
	que[1]=e;
	h=0;t=1;
	while(h<t)
	{
		h++;
		int x=que[h];
		fl[x]=0;
		if(vis[x]==0) continue;
		for(int i=hd[x];i!=0;i=a[i].next)
		{
			int k=a[i].to;
			if(dis[k]>dis[x]+1)
			{
				dis[k]=dis[x]+1;
				int k=a[i].to;
				if(fl[k]==0)
				{
				    fl[k]=1;
					t++;
					que[t]=k;
				}	
			}
		}
	}
	if(dis[s]==0x7fffffff/3) printf("-1\n");
      else  printf("%d\n",dis[s]);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_42920131/article/details/82951877