题解 P2296 【寻找道路】
打开题面看到“最短路径”马上就无脑打了dij
结果发现好像哪里不太对 好像不是普通最短路
但是 既然写了dij 那就尽量用吧
然后本菜鸡的这篇题解就出现了
第一遍dij
-
反向建图 标记所有无法到达的点
-
标记与已标记点相连的点
第二遍dij
- 正向建图 跳过标记点
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
const int maxn=10005;
const int maxm=200005;
int cnt,n,m,s,t;
int first[maxn],dis[maxn],u[maxm],v[maxm];
bool vis[maxn],b1[maxn],b2[maxn];
struct Edge
{
int to,dis,nxt;
}a[maxm];
struct Node
{
int num,dis;
};
inline int read()
{
int p=0,f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){p=(p<<1)+(p<<3)+(c^48),c=getchar();}
return p*f;
}
inline void addedge(int from,int to,int dis)
{
a[++cnt]=(Edge){to,dis,first[from]};
first[from]=cnt;
}
inline void init()
{
memset(vis,0,sizeof(vis));
for(int i=1;i<=n;i++)
dis[i]=2147483647;
}
bool operator <(Node a,Node b)
{
return a.dis>b.dis;
}
inline void dij(int s)
{
init();
priority_queue<Node>q;
q.push((Node){s,0});
dis[s]=0;
while(!q.empty())
{
int u=q.top().num;
q.pop();
if(vis[u]) continue;
vis[u]=1;
for(register int i=first[u];i;i=a[i].nxt)
{
int v=a[i].to;
if(b1[v]||b2[v]) continue;
if(dis[v]>dis[u]+a[i].dis)
{
dis[v]=dis[u]+a[i].dis;
q.push((Node){v,dis[v]});
}
}
}
}
int main()
{
n=read(),m=read();
for(register int i=1;i<=m;i++)
{
u[i]=read(),v[i]=read();
if(u[i]==v[i]) continue;
addedge(v[i],u[i],1);
}
s=read(),t=read();
dij(t);
for(register int i=1;i<=n;i++)
if(dis[i]==2147483647)
{
b1[i]=1;
for(register int j=first[i];j;j=a[j].nxt)
b2[a[j].to]=1;//尽量用另一个数组存,否则有后效性
}
memset(a,0,sizeof(a));
memset(first,0,sizeof(first));
cnt=0;
for(register int i=1;i<=m;i++)
{
if(u[i]==v[i]) continue;
addedge(u[i],v[i],1);
}
dij(s);
if(dis[t]==2147483647) cout<<"-1";
else cout<<dis[t];
return 0;
}