传送门
蒟蒻表示这题只会用BFS。。。
首先把输入的边反过来建,然后跑BFS,看终点可以跑到哪些点。
然后枚举所有点的邻接点,看看是否全部可以跑到终点。
然后把输入的图按照要求重构一遍。跑BFS求答案。。。
#include <cstdio>
#include <iostream>
#include <queue>
using namespace std;
const int maxm=210000;
int head[maxm],to[maxm],net[maxm],cnt;
int qhead[maxm],qto[maxm],qnet[maxm],qcnt;
int xhead[maxm],xto[maxm],xnet[maxm],xcnt;
bool flag[maxm],vis[maxm],ok[maxm];
int n,m,s,t;
struct node{
int x;
int step;
};
void add(int x,int y)
{
cnt++;
to[cnt]=y;
net[cnt]=head[x];
head[x]=cnt;
}
void qadd(int x,int y)
{
qcnt++;
qto[qcnt]=y;
qnet[qcnt]=qhead[x];
qhead[x]=qcnt;
}
void xadd(int x,int y)
{
xcnt++;
xto[xcnt]=y;
xnet[xcnt]=xhead[x];
xhead[x]=xcnt;
}
void BFS()
{
flag[t]=1;
queue <int> dl;
dl.push(t);
while(!dl.empty())
{
int d=dl.front();
dl.pop();
for(int i=xhead[d];i;i=xnet[i])
if(!flag[xto[i]])
flag[xto[i]]=1,dl.push(xto[i]);
}
}
int bfs()
{
queue <node> dl;
vis[s]=1;
dl.push((node){s,0});
while(!dl.empty())
{
node d=dl.front();
if(d.x==t)
return d.step;
dl.pop();
for(int i=qhead[d.x];i;i=qnet[i])
if(!vis[qto[i]])
vis[qto[i]]=1,dl.push((node){qto[i],d.step+1});
}
return -1;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
add(x,y);xadd(y,x);
}
scanf("%d%d",&s,&t);
BFS();
for(int i=1;i<=n;i++)
{
bool f=1;
for(int j=head[i];j;j=net[j])
if(!flag[to[j]])
{
f=0;
break;
}
ok[i]=f;
}
for(int i=1;i<=n;i++)
for(int j=head[i];j;j=net[j])
if(ok[to[j]])
qadd(i,to[j]);
if(flag[s]==0)
{
printf("-1\n");
}
else
printf("%d",bfs());
}