还是你谷
我永远爱洛谷.jpg
解析
作为一道折磨了我至少三四个小时的题,其实也不难
首先分为两个部分
1.给不能走的点染色
2.最短路
最短路的话,因为边长都是一,所以其实用bfs就可以(然而我还是弱智的用了SPFA)
关键是染色,如果正着搜的话不好写,所以我们存一个反图,然后找终点能到达的位置
然后把他们标记为能走;
接下来第二次染色,不能走的点,明显和他直接相连的点也是不可以走的,将他们的标记改成不能走(这时候要注意不能直接一边找一边改原来的标志数组,要另设一个数组,找完之后再改原数组)
然后最短路,这时候要注意因为我们存的是反图,所以要从终点找去起点的最短路(二者是等价的)
最后要注意的是,数组模拟邻接表储存的时候,next和to都是存边的,要按边的规模来设
(我调试三四个小时的罪魁祸首QAQ)
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int MAXN=10003;
struct deliver{
int next,to;
}a[200005];
int n,m,s,e;
int hd[MAXN],vis[MAXN],vv[MAXN],num1;
int h,t,dis[MAXN],fl[MAXN],que[2*MAXN+5];
inline void add(int u,int v)
{
a[++num1].next=hd[u];
a[num1].to=v;
hd[u]=num1;
}
void dfs(int k)
{
vis[k]=1;
for(int i=hd[k];i;i=a[i].next)
if(vis[a[i].to]==0) dfs(a[i].to);
}
int main()
{
scanf("%d%d",&n,&m);
int x1,y1;
for(int i=1;i<=m;i++)
{
scanf("%d%d",&x1,&y1);
if(x1!=y1) add(y1,x1);
}
scanf("%d%d",&s,&e);
dfs(e);//染色
for(int i=1;i<=n;i++)
if(vis[i]==0)
for(int j=hd[i];j;j=a[j].next)
vv[a[j].to]=1;
for(int i=1;i<=n;i++)
if(vv[i]==1) vis[i]=0;
for(int i=1;i<=n;i++)//最短路
dis[i]=0x7fffffff/3;
dis[e]=0;fl[e]=1;
que[1]=e;
h=0;t=1;
while(h<t)
{
h++;
int x=que[h];
fl[x]=0;
if(vis[x]==0) continue;
for(int i=hd[x];i!=0;i=a[i].next)
{
int k=a[i].to;
if(dis[k]>dis[x]+1)
{
dis[k]=dis[x]+1;
int k=a[i].to;
if(fl[k]==0)
{
fl[k]=1;
t++;
que[t]=k;
}
}
}
}
if(dis[s]==0x7fffffff/3) printf("-1\n");
else printf("%d\n",dis[s]);
return 0;
}