题目
一个有向图,要求满足要求的最短路径,要求为:
路径上的所有点的出边所指向的点都直接或间接与终点连通。
输入1
3 2 (3个点,2条边)
1 2 (1和2之间可以连接)
2 1
1 3 (从1到3)
输出1
-1
输入2
6 6
1 2
1 3
2 6
2 5
4 5
3 4
1 5
输出2
3
解题思路
其实我们就求出满足要求的点,然后在这些点里找最短路,还有本人这里的方法比较复杂和麻烦
代码
#include<cstdio>
using namespace std;
struct woc{int next,x,y;
};//日常邻接表
woc a[200001],lt[200001];
int xx,yy,n,m,k,state[10001],ls[10001],t,head,tail,f[10001],star,over;
int fls[10001];
bool ltfl[10001];
bool v[10001];
void check()//求所有可以直接或间接到终点的边
{int t=0;int head=0;int tail=1;state[1]=over;ltfl[state[1]]=true;//初始化while (head!=tail){head++;head=(head-1)%n+1;t=fls[state[head]];//求边while (t!=0){if (!ltfl[lt[t].y]){tail++;tail=(tail-1)%n+1;state[tail]=lt[t].y;ltfl[lt[t].y]=true;//标记}t=lt[t].next;//求下一条边}}
}
bool ok(int x)//是否满足要求
{int t=ls[x];while (t!=0){if (!ltfl[a[t].y]) return false;t=a[t].next;}return true;
}
int main()
{scanf("%d%d",&n,&m);state[1]=1;int u=0; for (int i=1;i<=m;i++){scanf("%d",&xx);scanf("%d",&yy);a[++u].next=ls[xx];ls[xx]=u;a[u].x=xx;a[u].y=yy;//边lt[u].next=fls[yy];fls[yy]=u;lt[u].y=xx;lt[u].x=yy;//记录一条回去的边} scanf("%d%d",&star,&over);for (int i=1;i<=n;i++) f[i]=2147483647;//初始化 check();//求所有可以直接或间接到终点的边head=0;tail=1;state[1]=star;v[state[1]]=true;f[star]=0;//初始化×2while (head!=tail){head++;//出队head=(head-1)%n+1;//循环队列t=ls[state[head]];while (t!=0){if (f[a[t].x]+1<f[a[t].y] && ok(a[t].y))//判断是否满足要求{f[a[t].y]=f[a[t].x]+1;//松弛if (!v[a[t].y]){tail++;//入队tail=(tail-1)%n+1;//循环队列state[tail]=a[t].y;v[a[t].y]=true;}}t=a[t].next;//下一条边}v[state[head]]=false;//解封}if (f[over]==2147483647) printf("-1");//是否有解else printf("%d\n",f[over]);
}