1. 程式人生 > >NOIP2014day2T2————尋找道路(road)

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

還是你谷 我永遠愛洛谷.jpg

解析

作為一道折磨了我至少三四個小時的題,其實也不難 首先分為兩個部分 1.給不能走的點染色 2.最短路 最短路的話,因為邊長都是一,所以其實用bfs就可以(然而我還是弱智的用了SPFA) 關鍵是染色,如果正著搜的話不好寫,所以我們存一個反圖,然後找終點能到達的位置 然後把他們標記為能走; 接下來第二次染色,不能走的點,明顯和他直接相連的點也是不可以走的,將他們的標記改成不能走(這時候要注意不能直接一邊找一邊改原來的標誌陣列,要另設一個數組,找完之後再改原陣列) 然後最短路,這時候要注意因為我們存的是反圖,所以要從終點找去起點的最短路(二者是等價的) 最後要注意的是,陣列模擬鄰接表儲存的時候,next和to都是存邊的,要按邊的規模

來設 (我除錯三四個小時的罪魁禍首)

#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;
}