洛谷 2296 寻找道路
【题解】
先建反向图,dfs求出哪些点可以到达终点。
再建正向图,dfs求出哪些点可以作为路径上的点。
最后在合法的点之间连边,跑dijkstra.
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #define LL long long 5 #define rg register 6 #define N 10010 7 #define M 200010 8 using namespace std; 9 int n,m,tot,st,ed,fa,son,last[N],dis[N],pos[N]; 10 bool arr[N],ok[N],vis[N]; 11 struct edge{int to,pre;}e[M]; 12 struct heap{int p,d;}h[N]; 13 struct rec{int u,v;}r[M]; 14 inline int read(){ 15 int k=0,f=1; char c=getchar(); 16 while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar(); 17 while('0'<=c&&c<='9')k=k*10+c-'0',c=getchar(); 18 return k*f; 19 } 20 void dfs(int x){ 21 arr[x]=1; 22 for(rg int i=last[x],to;i;i=e[i].pre)if(!arr[to=e[i].to]) dfs(to); 23 } 24 void dfs2(int x){ 25 vis[x]=1; bool can=1; 26 for(rg int i=last[x],to;i;i=e[i].pre){ 27 if(!arr[to=e[i].to]) can=0; 28 if(!vis[to]) dfs2(to); 29 } 30 ok[x]=can&arr[x]; 31 } 32 inline void up(int x){ 33 while((fa=x>>1)&&h[fa].d>h[x].d) swap(h[x],h[fa]),swap(pos[h[x].p],pos[h[fa].p]),x=fa; 34 } 35 inline void down(int x){ 36 while((son=x<<1)<=tot){ 37 if(h[son+1].d<h[son].d&&son<tot) son++; 38 if(h[son].d<h[x].d) swap(h[son],h[x]),swap(pos[h[son].p],pos[h[x].p]),x=son; 39 else return; 40 } 41 } 42 void dijkstra(int x){ 43 for(rg int i=1;i<=n;i++) dis[i]=1e9; 44 h[tot=pos[x]=1]=(heap){x,dis[x]=0}; 45 while(tot){ 46 int now=h[1].p; pos[h[tot].p]=1; h[1]=h[tot--]; if(tot) down(1); 47 for(rg int i=last[now],to;i;i=e[i].pre)if(dis[to=e[i].to]>dis[now]+1){ 48 dis[to]=dis[now]+1; 49 if(!pos[to]) h[pos[to]=++tot]=(heap){to,dis[to]}; 50 else h[pos[to]].d=dis[to]; 51 up(pos[to]); 52 } 53 } 54 } 55 int main(){ 56 n=read(); m=read(); 57 for(rg int i=1,u,v;i<=m;i++){ 58 u=r[i].u=read(),v=r[i].v=read(); 59 e[++tot]=(edge){u,last[v]}; last[v]=tot; 60 } 61 st=read(); ed=read(); 62 dfs(ed); 63 // for(rg int i=1;i<=n;i++) printf("%d ",arr[i]); puts("arr"); 64 65 memset(last,0,sizeof(last)); tot=0; 66 for(rg int i=1;i<=m;i++){ 67 int u=r[i].u,v=r[i].v; 68 e[++tot]=(edge){v,last[u]}; last[u]=tot; 69 } 70 dfs2(st); ok[ed]=1; 71 // for(rg int i=1;i<=n;i++) printf("%d ",ok[i]); puts("ok"); 72 if(!ok[st]){puts("-1"); return 0;} 73 74 memset(last,0,sizeof(last)); tot=0; 75 for(rg int i=1,u,v;i<=m;i++)if(ok[u=r[i].u]&&ok[v=r[i].v]) 76 e[++tot]=(edge){v,last[u]},last[u]=tot; 77 dijkstra(st); 78 if(dis[ed]!=1e9) printf("%d\n",dis[ed]); 79 else puts("-1"); 80 return 0; 81 }