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

题意:

给定一个有重边有自环的无向图,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 }

 

posted @ 2017-07-24 11:58  Neord  阅读(855)  评论(0编辑  收藏  举报