题目(vijos)
这题需要对原图进行重新构造。
首先,存图:因为要解决某个点是否能直接或间接与终点相连,所以我们对原图构一个反向图{e1}。当然,还要有一个原图{e2}。最后,我们还需要一个重构的图{e3},这个重构的图是干嘛用的呢?往后看。
然后,对反向图{e1}从终点开始跑一遍spfa,用以记录哪些点可以直接或间接到达终点,保存在can数组里面。
然后,对{e2}开始重构图:从起点开始重新接边,如果这条边指向的点无法直接或间接到达终点,那么这条边就不加进去。如果可以,那么这条边就加进去。重新构好的图就保存在{e3}。
最后,对{e3}跑一遍spfa。
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <cmath> #include <queue> const int INF=999999999; using namespace std; template <class ___E> inline void read(___E &e) { e=0;bool ck=0;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')ck=1;ch=getchar();} while(ch>='0'&&ch<='9'){e=e*10+ch-'0';ch=getchar();} if(ck) e = -e; } int n,m; int s,t; struct edge{ int vk; int next; }e1[200005],e2[200005],e3[200005]; //e1反向图,e2原图,e3重构的图 int hd1[10005],hd2[10005],hd3[10005]; int k1=1,k2=1,k3=1; int dis1[10005],dis2[10005]; bool vis[10005]; bool can[10005]; void ad1(int u,int v) { e1[k1].vk=v; e1[k1].next=hd1[u]; hd1[u]=k1++; } void ad2(int u,int v) { e2[k2].vk=v; e2[k2].next=hd2[u]; hd2[u]=k2++; } void ad3(int u,int v) { e3[k3].vk=v; e3[k3].next=hd3[u]; hd3[u]=k3++; } void sp1() { queue <int> q; for (int i=1;i<=n;++i) dis1[i]=INF; dis1[t]=0; vis[t]=1; q.push(t); while (!q.empty()) { int u=q.front(); q.pop(); vis[u]=0; for (int i=hd1[u];i;i=e1[i].next) { int v=e1[i].vk; if (dis1[v]>dis1[u]+1) { dis1[v]=dis1[u]+1; if (!vis[v]) { vis[v]=1; q.push(v); } } } } } void sp2() { queue <int> q; for (int i=1;i<=n;++i) dis2[i]=INF; dis2[s]=0; vis[s]=1; q.push(s); while (!q.empty()) { int u=q.front(); q.pop(); vis[u]=0; for (int i=hd3[u];i;i=e3[i].next) { int v=e3[i].vk; if (dis2[v]>dis2[u]+1) { dis2[v]=dis2[u]+1; if (!vis[v]) { vis[v]=1; q.push(v); } } } } } int main() { read(n),read(m); for (register int i=1;i<=m;++i) { int x,y; read(x),read(y); ad1(y,x); ad2(x,y); } read(s),read(t); sp1(); memset(vis,0,sizeof vis); for (register int i=1;i<=n;++i) can[i]=1; for (int k=1;k<=n;++k) { if (dis1[k]==INF) { for (int i=hd1[k];i;i=e1[i].next) { int v=e1[i].vk; can[v]=0; } } } for (int k=1;k<=n;++k) { for (int i=hd2[k];i;i=e2[i].next) { int v=e2[i].vk; if (can[v]) { ad3(k,v); } } } sp2(); if (dis2[t]==INF) printf("-1"); else printf( return 0; }
Comments NOTHING