Thank you for mr_wuyongcong’s help
题目描述:
在有向图G 中,每条边的长度均为1 ,现给定起点和终点,请你在图中找一条从起点到终点的路径,该路径满足以下条件:
1 .路径上的所有点的出边所指向的点都直接或间接与终点连通。
2 .在满足条件1 的情况下使路径最短。
注意:图G 中可能存在重边和自环,题目保证终点没有出边。
请你输出符合条件的路径的长度。
分析
首先,就是要找出不能到终点的点,然后再除了起点外,通向这些点这些点作废
代码
#include <cstdio>
using namespace std;
struct q{
int x,y,next;
}a[200001],b[200001];
int n,m,t,ls[10001],list[10001],en,st;
bool vv[10001],v[10001]; long long d[10001];
void fspfa(int stu){
int head=0,tail=1;
list[1]=stu;
do{
head++;
if (head>n) head=1;
t=d[list[head]];
while (t>0){
if (!vv[b[t].y]){
tail++;
if (tail>n) tail=1;
vv[b[t].y]=1;//标记可走路
list[tail]=b[t].y;
}
t=b[t].next;
}
}while (head!=tail);
}
bool pd(int t){
while (t>0){
if (!vv[a[t].y]) return false;//如果出边到不了终点点作废
t=a[t].next;
} return true;
}
void spfa(int st){
int head=0,tail=1;
for (int i=1;i<=n;i++) d[i]=2147483647;
list[1]=st; v[st]=1; d[st]=0;
do{
head++;
if (head>n) head=1;
t=ls[list[head]];
while (t>0){
if ((long long)d[a[t].x]+1<d[a[t].y]&&pd(ls[a[t].y])){
d[a[t].y]=d[a[t].x]+1;
if (!v[a[t].y]){
v[a[t].y]=1;
tail++;
if (tail>n) tail=1;
list[tail]=a[t].y;
}
}
t=a[t].next;
}
v[list[head]]=0;
}while (head!=tail);
if (d[en]==2147483647) printf("-1");
else printf("%d",d[en]);
}
int main(){
scanf("%d%d",&n,&m);
for (int i=1;i<=m;i++){//邻接表
scanf("%d%d",&a[i].x,&a[i].y);
a[i].next=ls[a[i].x];
ls[a[i].x]=i;
b[i].x=a[i].y;
b[i].y=a[i].x;
b[i].next=d[b[i].x];
d[b[i].x]=i;
} scanf("%d%d",&st,&en); vv[en]=1;
fspfa(en);//从终点找 spfa(st);//正常spfa
return 0;
}
#最后重申(head!=tail)是因为循环队列