您的位置:首页 > 其它

[noip2014]寻找道路 题解

2017-10-24 22:53 471 查看
emmmm,按照题意来做就好了。

首先,我们反向建边,从终点开始搜索,看能到哪儿些点,记录一下,再正向建边,看有哪儿些点连了这些点,把它们都排除就好了。

剩下的就是裸的最短路了。

#include<bits/stdc++.h>
#define N 10000
#define M 200000
using namespace std;
int n,m,s,t,inf;
int x[M+5],y[M+5];
int first[N+5],nxt[M+5],to[M+5],siz;
int vis[N+5],dis[N+5];
int Q[N+5],l,r,in[N+5];
inline void add(int x,int y)
{
nxt[siz]=first[x];
first[x]=siz;
to[siz]=y;
siz++;
}
inline void DFS(int x)
{
vis[x]=true;
for(int i=first[x];i!=-1;i=nxt[i])
{
int u=to[i];
if(!vis[u])DFS(u);
}
}
inline void SPFA(int s)
{
memset(dis,63,sizeof(dis));
inf=dis[s],dis[s]=0,Q[1]=s,l=0,r=1,in[s]=true;
if(vis[s]!=1)return;
while(l<r)
{
int x=Q[++l];in[x]=false;
for(int i=first[x];i!=-1;i=nxt[i])
{
int u=to[i];
if(vis[u]!=1)continue;
if(dis[x]+1<dis[u])
{
dis[u]=dis[x]+1;
if(in[u])continue;
in[u]=true;Q[++r]=u;
}
}
}
}
int main()
{
freopen("in.txt","r",stdin);
scanf("%d%d",&n,&m);
memset(first,-1,sizeof(first));
for(int i=1;i<=m;i++)scanf("%d%d",&x[i],&y[i]);
scanf("%d%d",&s,&t);
for(int i=1;i<=m;i++)add(y[i],x[i]);
DFS(t);
memset(first,-1,sizeof(first)),siz=0;
for(int i=1;i<=m;i++)add(x[i],y[i]);
for(int i=1;i<=n;i++)
for(int j=first[i];j!=-1;j=nxt[j])
if(!vis[to[j]])vis[i]=2;
SPFA(s);
cout<<(dis[t]==inf?-1:dis[t]);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: