题目描述 Description
在有向图G中,每条边的长度均为1,现给定起点和终点,请你在图中找一条从起点到终点的路径,该路径满足以下条件:
1.路径上的所有点的出边所指向的点都直接或间接与终点连通。
2.在满足条件1的情况下使路径最短。
注意:图G中可能存在重边和自环,题目保证终点没有出边。
请你输出符合条件的路径的长度。
输入描述 Input Description
第一行有两个用一个空格隔开的整数n和m,表示图有n个点和m条边。
接下来的m行每行2个整数x、y,之间用一个空格隔开,表示有一条边从点x指向点y。
最后一行有两个用一个空格隔开的整数s、t,表示起点为s,终点为t。
输出描述 Output Description
输出文件名为road.out。
输出只有一行,包含一个整数,表示满足题目描述的最短路径的长度。如果这样的路径不存在,输出-1。
首先,我们可以反向进行建边,以终点为起点bfs出每一条边的连通性,将反向能够连过的边的vis记为1。
接着,以起点为起点正着进行bfs,在添加now连接新的边i 进入队列之中需满足now连的所有边vis都不为0,即没有边与终点不连通,这样即可保证所有点的出边所指向的点都直接或间接与终点连通。注意一定要将重点的vis改为一个不为1的数,否则无法搜索到终点。
下附AC代码。
#include<iostream>
#include<vector>
#include<stdlib.h>
#include<queue>
#include<string.h>
#define maxn 10005
using namespace std;
int vis[maxn];
int n,m;
int f,t;
vector<int> zb[maxn];
vector<int> fb[maxn];
int cnt=0;
struct nod
{
int now,dis;
nod(int a,int b)
{
now=a;
dis=b;
}
nod(){}
};
queue<nod> q;
queue<nod> rq;
int num[maxn];
int dis[maxn];
void jianfanbian()
{
rq.push(nod(t,0));
vis[t]=1;
while(!rq.empty())
{
nod now=rq.front();
rq.pop();
num[now.now]=now.dis;
for(int i=0;i<fb[now.now].size();i++)
{
if(vis[fb[now.now][i]]==0)
{
rq.push(nod(fb[now.now][i],now.dis+1));
vis[fb[now.now][i]]=1;
}
}
}
num[t]=-1;
}
void qiuzhengjie()
{
memset(vis,0,sizeof(vis));
dis[f]=0;
vis[f]=1;
q.push(nod(f,0));
while(!q.empty())
{
nod now=q.front();
q.pop();
bool flag=true;
for(int i=0;i<zb[now.now].size();i++)
{
if(num[zb[now.now][i]]==0)
{
flag=false;
break;
}
}
if(flag==false)
continue;
dis[now.now]=now.dis;
for(int i=0;i<zb[now.now].size();i++)
{
if(vis[zb[now.now][i]]==0)
{
q.push(nod(zb[now.now][i],now.dis+1));
vis[zb[now.now][i]]=1;
}
}
if(dis[t])
{
cout<<dis[t]<<endl;
exit(0);
}
}
}
int main()
{
cin>>n>>m;
for(int i=1;i<=m;i++)
{
int a,b;
cin>>a>>b;
zb[a].push_back(b);
fb[b].push_back(a);
}
cin>>f>>t;
jianfanbian();
qiuzhengjie();
cout<<-1<<endl;
}