【NOIP 2014】寻找道路(dfs+spfa)

传送门

首先,肯定是先把所有满足条件一的点预处理出来,我们采用一遍dfs+一个统计来完成这件事。

然后就是求最短路了,跑一遍spfa即可。

#include<bits/stdc++.h>
#define N 10005
#define M 200005
using namespace std;
int n,m,first[N],tot,s,t,zdl[N];
bool able[N],walk[N],true_able[N];
struct save
{
	int x,y;
}bian[M];
struct node
{
	int to,next;
}edge[M];
inline void addedge(int x,int y)
{
	tot++;
	edge[tot].to=y;
	edge[tot].next=first[x];
	first[x]=tot;
}
void dfs(int now)
{
	able[now]=true;
	for(int u=first[now];u;u=edge[u].next)
	{
		if(!able[edge[u].to])	dfs(edge[u].to);
	}
}
queue <int> q;
inline void spfa(int s)
{
	memset(zdl,127,sizeof(zdl));
	
	walk[s]=true;
	zdl[s]=0;
	q.push(s);
	while(!q.empty())
	{
		int now=q.front();
		q.pop();
		walk[now]=false;
		for(int u=first[now];u;u=edge[u].next)
		{
			int vis=edge[u].to;
			if(!true_able[vis])	continue;
			if(zdl[now]+1<zdl[vis])
			{
				zdl[vis]=zdl[now]+1;
				if(!walk[vis])
				{
					q.push(vis);
					walk[vis]=true;
				}
			}
		}
	}
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(NULL),cout.tie(NULL);
	cin>>n>>m;
	for(int i=1;i<=m;i++)
	{
		int x,y;
		cin>>x>>y;
		addedge(y,x);
		bian[i].x=x,bian[i].y=y;
	}
	cin>>s>>t;
	dfs(t);
	
	memset(edge,0,sizeof(edge));
	memset(first,0,sizeof(first));
	tot=0;
	
	for(int i=1;i<=m;i++) addedge(bian[i].x,bian[i].y);

	for(int i=1;i<=n;i++)
	{
		int flag=true;
		for(int u=first[i];u;u=edge[u].next)
		{
			int vis=edge[u].to;
			if(!able[vis])	flag=false;
		} 
		if(flag==false)	true_able[i]=false;
		else true_able[i]=true;
	}
	spfa(s);
	
	if(zdl[t]==2139062143)	cout<<"-1";
	else cout<<zdl[t];
	return 0;
} 
posted @ 2018-08-10 09:35  Patrickpwq  阅读(172)  评论(0)    收藏  举报