您的位置:首页 > 其它

UOJ 19 [NOIP2014]寻找道路

2016-08-29 18:12 357 查看
图的遍历+最短路。

第一眼看,好难,不会做。

仔细一看,发现只要一次反向边BFS把不合题意的点全部丢掉就可以直接跑最短路了- -

顺利打完之后被hack成97分,原因是没有判断起点直接不可取的情况。改后AC。

#include<cstdio>
#include<queue>
#include<cstring>
#define N 10005
#define M 200005
using namespace std;
struct edge{int next,to;}e[M<<1];
int cnt=0, last[2]
, n, m, s, t, d
;
bool vis
, ban
, inq
;
void add(int i, int a, int b)
{
e[++cnt]=(edge){last[i][a],b};
last[i][a]=cnt;
}
void bfs(int beg)
{
queue<int> q;
q.push(beg);
vis[beg]=1;
while(!q.empty())
{
int x=q.front();
q.pop();
for(int i = last[1][x]; i; i=e[i].next)
{
int y=e[i].to;
if(vis[y])continue;
vis[y]=1;
q.push(y);
}
}
}
void solve()
{
for(int i = 1; i <= n; i++)
if(!vis[i])
for(int j = last[1][i]; j; j=e[j].next)
ban[e[j].to]=1;
}
int SPFA(int beg, int end)
{
if(ban[beg])return -1;
memset(d,63,sizeof(d));
queue<int> q;
q.push(beg);
d[beg]=0;
while(!q.empty())
{
int x=q.front();
q.pop();
inq[x]=0;
for(int i = last[0][x]; i; i=e[i].next)
{
int y=e[i].to;
if(ban[y] || d[x]+1>=d[y])continue;
d[y]=d[x]+1;
if(!inq[y])
{
inq[y]=1;
q.push(y);
}
}
}
return d[end];
}
int main()
{
scanf("%d%d",&n,&m);
for(int a, b, i = 1; i <= m; i++)
{
scanf("%d%d",&a,&b);
add(0,a,b);
add(1,b,a);
}
scanf("%d%d",&s,&t);
bfs(t);
solve();
int ans = SPFA(s, t);
printf("%d\n",ans>N?-1:ans);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: