NOIP2014 寻找道路
这道题还是比较简单的。我们只要先用老套路建出反图,记录终点与哪些点是联通的,之后从所有不与终点联通的点出发,在反图上枚举一下与之直接相连的边,也设为不能走。之后我们在可以走的路上跑最短路即可。
看一下代码。
#include<cstdio> #include<algorithm> #include<cstring> #include<iostream> #include<cmath> #include<queue> #include<set> #define rep(i,a,n) for(int i = a;i <= n;i++) #define per(i,n,a) for(int i = n;i >= a;i--) #define pr pair<int,int> #define mp make_pair #define fi first #define sc second #define enter putchar('\n') using namespace std; typedef long long ll; const int M = 100005; const int INF = 1000000009; int read() { int ans = 0,op = 1; char ch = getchar(); while(ch < '0' || ch > '9') { if(ch == '-') op = -1; ch = getchar(); } while(ch >= '0' && ch <= '9') ans *= 10,ans += ch - '0',ch = getchar(); return ans * op; } struct edge { int next,to,from; }e[M<<2],e1[M<<2]; int n,m,head[M],ecnt,dis[M],S,T,head1[M],ecnt1,x,y; bool vis[M],pd[M]; queue <int> Q; set <pr> q; set <pr> :: iterator it; void add(int x,int y) { e[++ecnt].to = y; e[ecnt].next = head[x]; e[ecnt].from = x; head[x] = ecnt; } void add1(int x,int y) { e1[++ecnt1].to = y; e1[ecnt1].next = head1[x]; e1[ecnt1].from = x; head1[x] = ecnt1; } void bfs() { Q.push(T);vis[T] = 1; while(!Q.empty()) { int k = Q.front();Q.pop(); for(int i = head1[k];i;i = e1[i].next) { int v = e1[i].to; if(!vis[v]) vis[v] = 1,Q.push(v); } } } void dij() { dis[S] = 0; q.insert(mp(0,S)); while(!q.empty()) { pr k = *(q.begin());q.erase(q.begin()); for(int i = head[k.sc];i;i = e[i].next) { if(!vis[e[i].to] || pd[e[i].to]) continue; if(dis[e[i].to] > dis[k.sc] + 1) { it = q.find(mp(dis[e[i].to],e[i].to)); if(it != q.end()) q.erase(it); dis[e[i].to] = dis[k.sc] + 1; q.insert(mp(dis[e[i].to],e[i].to)); } } } } int main() { n = read(),m = read(); rep(i,1,n) dis[i] = INF; rep(i,1,m) x = read(),y = read(),add(x,y),add1(y,x); S = read(),T = read(); bfs(); rep(i,1,n) if(!vis[i]) { for(int j = head1[i];j;j = e1[j].next) pd[e1[j].to] = 1; } dij(); if(dis[T] == INF) printf("-1\n"); else printf("%d\n",dis[T]); return 0; }
当你意识到,每个上一秒都成为永恒。