寻找道路

【问题述】

在有向图G中,每条边的长度均为1,现给定起点和终点,请你在图中找一条从起点到终点的路径,该路径满足以下条件:

1.路径上的所有点的出边所指向的点都直接或间接与终点连通。

2.在满足条件1的情况下使路径最短。

注意:图G中可能存在重边和自环,题目保证终点没有出边。

请你输出符合条件的路径的长度。

 

【输入】

输入文件名为road.in。

第一行有两个用一个空格隔开的整数n和m,表示图有n个点和m条边。

接下来的m行每行2个整数x、y,之间用一个空格隔开,表示有一条边从点x指向点y。

最后一行有两个用一个空格隔开的整数s、t,表示起点为s,终点为t。

 

【输出】

输出文件名为road.out。

输出只有一行,包含一个整数,表示满足题目描述的最短路径的长度。如果这样的路径不存在,输出-1。

 

【输入输出样例1】

road.in

road.out

3 2

1 2

2 1

1 3

-1

 

 

【输入输出样例说明】

 

如上图所示,箭头表示有向道路,圆点表示城市。起点1与终点3不连通,所以满足题目描述的路径不存在,故输出-1。

 

【输入输出样例2】

road.in

road.out

6 6

1 2

1 3

2 6

2 5

4 5

3 4

1 5

3

 

【输入输出样例说明】

 

如上图所示,满足条件的路径为1->3->4->5。注意点2不能在答案路径中,因为点2连了一条边到点6,而点6不与终点5连通。

 

【数据说明】

对于30%的数据,0< n ≤10,0< m ≤20;

对于60%的数据,0< n ≤100,0< m ≤2000;

对于100%的数据,0< n ≤10,000,0< m ≤200,000,0< x,y,s,t≤n,x≠t。


 思路:

说实话,我一开始没想到用广搜,以为就是一道基本的图论题,这道题告诉我们,有时候逆向思维很重要

因为我们要建反边,从终点倒着遍历一遍,打上标记,表明是可以到达终点的点

再枚举一遍,找出所有没打标记的点,这些点的扩展如果打上标记,我们就需要清除掉,因为已经不符合题目条件

最后再倒着遍历一遍,就可以更新出答案啦

 

代码:(打“//” 说明易错哦)

#include<stdio.h>
#include<string.h> 
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
const int M=10001,X=200001;
vector<int> edge[M];
queue<int> q;
int n,m,st,ed,ans[M];
bool vis[X],upd[X];

int main()
{
    scanf("%d%d",&n,&m); 
    for(int i=1;i<=m;++i)
    {
        int u,v;
        scanf("%d%d",&u,&v);
        if(u==v) continue;
        edge[v].push_back(u);
    }
    scanf("%d%d",&st,&ed);
    vis[ed]=1; //
    q.push(ed);
    while(!q.empty())
    {
        int cur=q.front();
        q.pop();
        for(int i=0;i<edge[cur].size();++i) //
        {
            int next=edge[cur][i];
            if(!vis[next]) 
            {
                vis[next]=1;
                q.push(next);
            }
        }
    }
    memcpy(upd,vis,sizeof(vis));
    for(int i=1;i<=n;++i) 
        if(!vis[i]) 
            for(int j=0;j<edge[i].size();++j)
            {
                int next=edge[i][j];
                if(upd[next]) {
                    upd[next]=0; //
                }
            }
    q.push(ed);
    while(!q.empty())
    {
        int cur=q.front();
        q.pop();
        for(int i=0;i<edge[cur].size();++i)
        {
            int next=edge[cur][i];
            if(upd[next]) 
            {
                q.push(next); //
                upd[next]=0;
                ans[next]=ans[cur]+1;
            }
        }
    }
    if(!ans[st]) printf("-1");
    else printf("%d",ans[st]);
    return 0;
}

 

posted @ 2018-09-10 13:25  qseer  阅读(144)  评论(0编辑  收藏  举报