【NOIP2014】尋找道路
阿新 • • 發佈:2018-10-31
演算法:
先反向建圖,從終點開始BFS,找出所有與其連通的點
其次,考慮到圖不一定聯通,我們特殊處理那些壓根就不會與終點在一個聯通塊裡的點
最後,愉快單源最短路即可
Code:
#include<bits/stdc++.h> #define rep(i,j,k) for(int i=j;i<=k;i++) using namespace std; template<typename T> void chkmin(T &x,T y){x=x<y?x:y;} template<typename T> void read(T &num){ char c=getchar();T f=1;num=0; while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){num=(num<<3)+(num<<1)+(c^48);c=getchar();} num*=f; } template<typename T> void qwq(T x){ if(x>9)qwq(x/10); putchar(x%10+'0'); } template<typename T> void write(T x){ if(x<0){x=-x;putchar('-');} qwq(x);putchar('\n'); } int n,m; struct wzy{ int nxt,vertice; }edge[200010]; int head[10010];int len1=0; inline void add_edge(int x,int y){ edge[++len1].nxt=head[x];edge[len1].vertice=y;head[x]=len1; return; } int s,t;bool wjp[10010];bool hashs[10010]; queue<int>v; inline void Pretreatment(){ v.push(t);wjp[t]=1; while(!v.empty()){ int nop=v.front();v.pop(); for(int i=head[nop];i;i=edge[i].nxt){ int temp=edge[i].vertice; if(!wjp[temp]){wjp[temp]=1;v.push(temp);} } } return; } int dis[10010];bool in[10010]; inline void SPFA(){ v.push(t);dis[t]=0;in[t]=1; while(!v.empty()){ int nop=v.front();in[nop]=0;v.pop(); for(int i=head[nop];i;i=edge[i].nxt){ int temp=edge[i].vertice; if(!hashs[temp])continue; if(dis[temp]>dis[nop]+1){ chkmin(dis[temp],dis[nop]+1); if(!in[temp]){in[temp]=1;v.push(temp);} } } } return; } int main(){ read(n);read(m); rep(i,1,m){ int x,y;read(x);read(y); if(x!=y)add_edge(y,x); } read(s);read(t); memset(dis,0x3f,sizeof(dis)); Pretreatment(); memcpy(hashs,wjp,sizeof(wjp)); rep(i,1,n){ if(wjp[i])continue; for(int j=head[i];j;j=edge[j].nxt){ int nop=edge[j].vertice; if(hashs[nop])hashs[nop]=0; } } SPFA(); write((dis[s]>n)?-1:dis[s]); return 0; }