NOIP2014day2T2————尋找道路(road)
阿新 • • 發佈:2018-12-13
還是你谷 我永遠愛洛谷.jpg
解析
作為一道折磨了我至少三四個小時的題,其實也不難
首先分為兩個部分
1.給不能走的點染色
2.最短路
最短路的話,因為邊長都是一,所以其實用bfs就可以(然而我還是弱智的用了SPFA)
關鍵是染色,如果正著搜的話不好寫,所以我們存一個反圖,然後找終點能到達的位置
然後把他們標記為能走;
接下來第二次染色,不能走的點,明顯和他直接相連的點也是不可以走的,將他們的標記改成不能走(這時候要注意不能直接一邊找一邊改原來的標誌陣列,要另設一個數組,找完之後再改原陣列)
然後最短路,這時候要注意因為我們存的是反圖,所以要從終點找去起點的最短路(二者是等價的)
最後要注意的是,陣列模擬鄰接表儲存的時候,next和to都是存邊的,要按邊的規模
#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; }