寻找道路(NOIP2014)神奇之题。。

原题传送门

这道题嘛。。

首先根据题目,我们要先知道哪些点能够到达终点。(反向BFS)

然后我们再求最短路的途中,必须随时判断周围的点是否被第一次BFS标记过。、

所以再来一次BFS。

数组记得清零,不然会炸。。

下面贴代码

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int n,m,num=0,s,tt;
int q[20000];
int step[20000];
int head[10001];
bool vis[10001];
int a[200001],b[200001];
struct edge{
    int to,next;
}g[400001];
void ins(int u,int v)
{
    g[++num].next=head[u];
    head[u]=num;
    g[num].to=v;
}
void bfs1(int last){
    vis[last]=true;
    int h=1,t=1;
    q[h]=last;
    while(h<=t)
    {
        int tmp=q[h];
        for(int i=head[tmp];i;i=g[i].next)
        if(!vis[g[i].to])
        {
            vis[g[i].to]=true;
            q[++t]=g[i].to;        
        }
        h++;    
    }
}
bool chubian(int q){
    for(int i=head[q];i;i=g[i].next)
    if(!vis[g[i].to]) return false;
    return true;
}
bool bfs2(int first){
    memset(q,0,sizeof(q));
    int h=1,t=1;
    q[h]=first;
    while(h<=t)
    {
        int tmp=q[h++];
        if(!chubian(tmp))continue;
        for(int i=head[tmp];i;i=g[i].next)
        if(step[g[i].to]==0)
        {
            step[g[i].to]=step[tmp]+1;
            if(g[i].to==tt){printf("%d\n",step[tt]);return true;}
            q[++t]=g[i].to;
        }
    }
    return false;
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d",&a[i],&b[i]);
        ins(b[i],a[i]);    
    }
    scanf("%d%d",&s,&tt);
    bfs1(tt);
    memset(head,0,sizeof(head));
    memset(g,0,sizeof(g));
    num=0;
    for(int i=1;i<=m;i++)
    ins(a[i],b[i]);
    if(!bfs2(s))printf("-1\n");
}

 

posted @ 2017-05-15 16:40  ghostfly233  阅读(204)  评论(0编辑  收藏  举报