UVa 1599 (字典序最小的最短路) Ideal Path

题意:

给出一个图(图中可能含平行边,可能含环),每条边有一个颜色标号。在从节点1到节点n的最短路的前提下,找到一条字典序最小的路径。

分析:

首先从节点n到节点1倒着BFS一次,算出每个节点到节点n个最短距离di

然后从节点1开始再一次BFS,在寻找下一个节点时,必须满足下一个节点v满足对于当前节点u,有du = dv + 1,这样才能保证在最短路上。

在这个条件下还要满足v的颜色编号是最小的。因为可能有多个颜色相同的最小编号,所以这些节点都要保留下来。

 

图的表示方式:这里如果再用往常的邻接表发现不适用了,所以G[u]中保存的与u邻接的edges中边的编号。

  1 #include <cstdio>
  2 #include <vector>
  3 #include <cstring>
  4 #include <queue>
  5 #include <algorithm>
  6 using namespace std;
  7 
  8 const int maxn = 100000 + 10;
  9 const int INF = 1000000000 + 10;
 10 
 11 struct Edge
 12 {
 13     int u, v, c;
 14     Edge(int u=0, int v=0, int c=0):u(u), v(v), c(c) {}
 15 };
 16 
 17 vector<Edge> edges;
 18 vector<int> G[maxn];
 19 
 20 void AddEdge(int u, int v, int c)
 21 {
 22     edges.push_back(Edge(u, v, c));
 23     int index = edges.size() - 1;
 24     G[u].push_back(index);
 25 }
 26 
 27 int n, d[maxn];
 28 bool vis[maxn];
 29 vector<int> ans;
 30 
 31 void rev_bfs()
 32 {
 33     memset(vis, 0, sizeof(vis));
 34     queue<int> q;
 35     q.push(n-1);
 36     vis[n-1] = true;
 37     d[n-1] = 0;
 38 
 39     while(!q.empty())
 40     {
 41         int u = q.front(); q.pop();
 42         for(int i = 0; i < G[u].size(); ++i)
 43         {
 44             int e = G[u][i];
 45             int v = edges[e].v;
 46             if(!vis[v])
 47             {
 48                 vis[v] = true;
 49                 d[v] = d[u] + 1;
 50                 q.push(v);
 51             }
 52         }
 53     }
 54 }
 55 
 56 void bfs()
 57 {
 58     memset(vis, 0, sizeof(vis));
 59     vis[0] = true;
 60     ans.clear();
 61 
 62     vector<int> next;
 63     next.push_back(0);
 64     for(int i = 0; i < d[0]; ++i)
 65     {
 66         int min_color = INF;
 67         for(int j = 0; j < next.size(); ++j)
 68         {
 69             int u = next[j];
 70             for(int k = 0; k < G[u].size(); ++k)
 71             {
 72                 int e = G[u][k];
 73                 int v = edges[e].v;
 74                 if(d[u] == d[v] + 1)
 75                     min_color = min(min_color, edges[e].c);
 76             }
 77         }
 78         ans.push_back(min_color);
 79 
 80         vector<int> next2;
 81         for(int j = 0; j < next.size(); ++j)
 82         {
 83             int u = next[j];
 84             for(int k = 0; k < G[u].size(); ++k)
 85             {
 86                 int e = G[u][k];
 87                 int v = edges[e].v;
 88                 if(!vis[v] && d[u] == d[v] + 1 && edges[e].c == min_color)
 89                 {
 90                     vis[v] = true;
 91                     next2.push_back(v);
 92                 }
 93             }
 94         }
 95         next = next2;
 96     }
 97 
 98     printf("%d\n%d", d[0], ans[0]);
 99     for(int i = 1; i < ans.size(); ++i) printf(" %d", ans[i]);
100     puts("");
101 }
102 
103 int main()
104 {
105     //freopen("in.txt", "r", stdin);
106     int m, u, v, c;
107     while(scanf("%d%d", &n, &m) == 2)
108     {
109         edges.clear();
110         for(int i = 0; i < n; ++i) G[i].clear();
111         while(m--)
112         {
113             scanf("%d%d%d", &u, &v, &c);
114             if(u == v) continue;    //最短路中一定不含环
115             AddEdge(u-1, v-1, c);
116             AddEdge(v-1, u-1, c);
117         }
118 
119         rev_bfs();
120         bfs();
121     }
122 
123     return 0;
124 }
代码君

 

posted @ 2015-02-02 10:28  AOQNRMGYXLMV  阅读(923)  评论(0编辑  收藏  举报