题意:有n个技能 m个条件 接下来是两个终极技能的编号
m个条件是 x y 代表必须y的前置技能是x
只要学会任意一个前置技能就能学当前技能
问把两个终极技能学了至少要学多少前置技能
题解:先用第一个终极技能跑一个最短路 再用第二个跑最短路
枚举他们两个的交点 然后去min即可
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
const int maxn=211111;
struct renode{
int to,nxt;
}reed[maxn<<1];
int rehead[maxn];
struct node{
int to,nxt;
}ed[maxn<<1];
int head[maxn],cnt;
void addedge(int u,int v){
ed[cnt].to=v;
ed[cnt].nxt=head[u];
reed[cnt].to=u;
reed[cnt].nxt=rehead[v];
head[u]=rehead[v]=cnt;
cnt++;
}
int dis[maxn],disa[maxn],disb[maxn];
queue<int>q;
int main()
{
int n,m,a,b;
memset(head,-1,sizeof(head));
memset(rehead,-1,sizeof(head));
memset(dis,-1,sizeof(head));
memset(disa,-1,sizeof(disa));
memset(disb,-1,sizeof(disb));
scanf("%d%d%d%d",&n,&m,&a,&b);
for(int i=1;i<=m;i++){
int u,v;
scanf("%d%d",&u,&v);
addedge(u,v);
}
dis[0]=0;
q.push(0);
while(!q.empty()){
int u=q.front();q.pop();
for(int i=head[u];~i;i=ed[i].nxt){
int v=ed[i].to;
if(dis[v]==-1){
dis[v]=dis[u]+1;
q.push(v);
}
}
}
disa[a]=0;
q.push(a);
while(!q.empty()){
int u=q.front();q.pop();
for(int i=rehead[u];~i;i=reed[i].nxt){
int v=reed[i].to;
if(disa[v]==-1){
disa[v]=disa[u]+1;
q.push(v);
}
}
}
disb[b]=0;
q.push(b);
while(!q.empty()){
int u=q.front();q.pop();
for(int i=rehead[u];~i;i=reed[i].nxt){
int v=reed[i].to;
if(disb[v]==-1){
disb[v]=disb[u]+1;
q.push(v);
}
}
}
int ans=-1;
for(int i=0;i<=n;i++){
int step;
if(dis[i]==-1||disa[i]==-1||disb[i]==-1)continue;
step=disb[i]+disa[i]+dis[i];
if(ans==-1||step<ans)ans=step;
}
printf("%d\n",ans);
return 0;
}