题目描述 https://www.luogu.org/problemnew/show/P2296
这道题有个坑,虽然没掉进去,但是没跨过去
坑is here 路径上的所有点的出边所指向的点都直接或间接与终点连通。
所以就需要建反图 来删去一些没用的点
从终点倒着找 搜索不到的点就删去 与这些点直接相连的点也删去
要注意做标记的时候 要用一个新的数组 以防其他的被改变
还有就是数组模拟邻接表的应用
看代码吧
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int b[10050],q[2000050],st[10050],h[10050],f[10050],f2;
struct road
{
int next,to;
};
road edge[2000050];
void bfs1(int x)
{
int t=1,ha=1;
q[t]=x; b[x]=0;
while(ha<=t)
{
x=q[ha];
for(int i=h[x];i>0;i=edge[i].next)
if(b[edge[i].to]==1)
{
t++;
q[t]=edge[i].to;
b[edge[i].to]=0;
}
ha++;
}
}
void bfs2(int x,int y)
{
int t=1,ha=1;
memset(q,0,sizeof(q));
q[t]=x;
while(ha<=t)
{
x=q[ha];
for(int i=h[x];i>0;i=edge[i].next)
if(b[edge[i].to]==0)
{
t++;
q[t]=edge[i].to;
st[t]=st[ha]+1;
if(q[t]==y){ cout<<st[t]; f2=1; return;}
b[edge[i].to]=1;
}
ha++;
}
}
int main()
{ int x,y,i,j,n,m,s,t;
freopen("road.in","r",stdin);
freopen("road.out","w",stdout);
cin>>n>>m;
for(i=1;i<=n;i++) b[i]=1;
for(i=1;i<=m;i++)
{
cin>>x>>y;
edge[i].next=h[y];
edge[i].to=x; h[y]=i;
}
cin>>s>>t; bfs1(t);//找到从终点能遍历的点
for(i=1;i<=n;i++)
if(b[i]==1)
for(j=h[i];j>0;j=edge[j].next)
f[edge[j].to]=1;//找到与删去的点直接相连的点
for(i=1;i<=n;i++)
if(b[i]==0&&f[i]==1)
b[i]=1;//结合两个标记
bfs2(t,s);//从终点开始找最短路径
if(f2==0) cout<<"-1";
fclose(stdin); fclose(stdout);
return 0;
}