1. 程式人生 > >UVa 1599 理想路徑(反向BFS 求最短路徑 )

UVa 1599 理想路徑(反向BFS 求最短路徑 )

ack pan clu inf struct name esp turn pop

題意:

給定一個有重邊有自環的無向圖,n個點(2 <= n <= 100000), m條邊(1 <= m <= 200000), 每條邊有一個權值, 求從第一個點到n的最少步數, 如果最少步數相同有多條路徑, 那麽輸出權值字典序最小的一條。

分析:

用BFS解決最短路問題, 可以先從終點BFS, 求出每個點到終點的最短距離。 那麽最少步數就是起點的最短距離, 最短路徑就是從起點每次向最短距離比自己少1的頂點移動(如果有多個則可以隨便走), 這樣就可以保證走的是最短路徑, 如果一開始我們是從起點BFS, 那麽這樣則不能保證走的是通往終點的最短路徑。然後我們就可以從起點出發, 循環最短距離次, 每次選擇字典序最少的走, 如果有多個字典序相同則選擇多個, 直到走完最短距離, 就可以得出答案。 註意兩次BFS都需要添加標記, 不然重邊很可能就會導致TLE。

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 const int maxm = 1e7;
  4 const int maxn = 1e6 + 7;
  5 const int inf = 1e9;
  6 struct Node{
  7     int v,col,next;
  8     Node():v(0),col(0),next(0){}
  9 };
 10 struct ele{
 11     int v;
 12     int dist;
 13     ele(int v, int dist):v(v),dist(dist){}
14 }; 15 16 Node edge[maxn]; 17 int G[maxn], d[maxn]; 18 bool vis[maxn]; 19 int n, m, cnt; 20 21 void build(){ 22 memset(G,-1,sizeof(G)); 23 cnt = 0; 24 for(int i = 0; i < m; i++){ 25 int u, v, col; 26 scanf("%d %d %d", &u, &v, &col);
27 if(u == v) continue; 28 edge[cnt].v = v; 29 edge[cnt].col = col; 30 edge[cnt].next = G[u]; 31 G[u] = cnt++; 32 edge[cnt].v = u; 33 edge[cnt].col = col; 34 edge[cnt].next = G[v]; 35 G[v] = cnt++; 36 } 37 } 38 39 void revbfs(){ 40 fill(d,d+maxn, inf); 41 memset(vis,0,sizeof(vis)); 42 queue<ele> q; 43 q.push(ele(n,0)); 44 d[n] = 0; 45 vis[n] = 1; 46 while(!q.empty()){ 47 ele u = q.front(); q.pop(); 48 d[u.v] = u.dist; 49 for(int i = G[u.v]; i != -1; i = edge[i].next){ 50 int v = edge[i].v; 51 if(d[v] < u.dist + 1 || vis[v]){ 52 continue; 53 } 54 q.push(ele(v,u.dist+1)); 55 vis[v] = 1; 56 } 57 } 58 } 59 void bfs(){ 60 vector<int> path; 61 memset(vis,0,sizeof(vis)); 62 vis[1] = 1; 63 vector<int> next; 64 next.push_back(1); 65 for(int i = 0; i < d[1]; i++){//the essential minimum step 66 int min_col = inf; 67 for(int j = 0; j < next.size(); j++){ 68 int u = next[j]; 69 for(int k = G[u]; k != -1; k = edge[k].next){ 70 int v = edge[k].v; 71 if(d[u] == d[v] + 1) 72 min_col = min(min_col,edge[k].col); 73 } 74 } 75 //find out the minimum color 76 path.push_back(min_col); 77 78 vector<int> next2; 79 for(int j = 0; j < next.size(); j++){ 80 int u = next[j]; 81 for(int k = G[u]; k != -1; k= edge[k].next){ 82 int v = edge[k].v; 83 if(d[u] == d[v] + 1 && !vis[v] && edge[k].col == min_col){ 84 vis[v] = 1; 85 next2.push_back(v); 86 } 87 } 88 } 89 next = next2; 90 } 91 92 93 printf("%d\n%d",(int)path.size(),path[0]); 94 for(int i = 1; i < path.size(); i++){ 95 printf(" %d",path[i]); 96 } 97 puts(""); 98 } 99 int main(){ 100 freopen("1.txt","r",stdin); 101 while(~scanf("%d %d", &n, &m)){ 102 build(); 103 revbfs();//反向bfs求出終點到每個點的最短距離 104 bfs(); 105 } 106 printf("%.3f",(double)clock()/CLOCKS_PER_SEC); 107 return 0; 108 }

UVa 1599 理想路徑(反向BFS 求最短路徑 )