理想路径,P173Uva1599

来源:互联网 发布:民国报纸数据库 编辑:程序博客网 时间:2024/05/21 09:01

这也是一道非常好的无向图最短路问题。其中在边上增加了颜色条件,使得稍微复杂一些。刘的此篇代码使我在无向图最短路的算法实现上有很大的收获。下面直接进行干货总结:
语法细节:
1.结构体的无参构造函数:
struct Edge {
int u, v, c;
Edge(int u=0, int v=0, int c=0):u(u),v(v),c(c) {}
};
2.任何结构体和类都可以无对象实体传参。
edges.push_back(Edge(u, v, c));//语法积累

算法思路:
1.图的存储。自己过去对于图的存储仅仅理解为数组的形式。尽管关于本题可以用一个二维数组来记录arr[n1][n2] = color;但是此种存储的弊端是仅仅记录了点与点之间相连,但是无法快速查找与节点n相连的节点有哪个。因此在遍历搜索的时候,时间复杂度大大提高。而刘却解决了此问题。刘将所有的路径信息保存在一个结构体数组中,然后再将结构体数组中从n出发的边的位置记录在G[n]之中,这样就在图的存储的时候记录下了每个节点的相邻节点,为之后的遍历打下了基础。
2.求连通分之用DFS,求最短路用BFS。DFS用递归,BFS用队列。但是无论DFS还是BFS图的遍历一定要有标记数组,防止查重。
3.先反向BFS,从求出每个节点到目标节点的最短距离。
4.然后在正向BFS从起点开始走,对它的连接节点做两次遍历,第一次查找到目标节点最短距离比它少1的节点中最小的颜色,第二次在遍历一遍,把符合这两个条件(1.到目标节点最短距离比它少1。2.节点颜色是刚才查找出的最小颜色)的节点入队。
5.继续BFS出结果。

// UVa1599 Idea Path// Rujia Liu#include<cstdio>#include<cstring>#include<vector>#include<queue>using namespace std;const int maxn = 100000 + 5;const int INF = 1000000000; // maximal colorstruct Edge {  int u, v, c;  Edge(int u=0, int v=0, int c=0):u(u),v(v),c(c) {}};vector<Edge> edges;vector<int> G[maxn];void AddEdge(int u, int v, int c) {  edges.push_back(Edge(u, v, c));//语法积累   int idx = edges.size() - 1;  G[u].push_back(idx);}int n, vis[maxn];int d[maxn];// reverse bfs to find out the distance from each node to n-1void rev_bfs() {  memset(vis, 0, sizeof(vis));  d[n-1] = 0;  vis[n-1] = true;  queue<int> q;  q.push(n-1);  while(!q.empty()) {    int v = q.front(); q.pop();    for(int i = 0; i < G[v].size(); i++) {      int e = G[v][i];      int u = edges[e].v;      if(!vis[u]) {        vis[u] = true;        d[u] = d[v] + 1;        q.push(u);      }    }  }}vector<int> ans;// forward bfs to construct the pathvoid bfs() {  memset(vis, 0, sizeof(vis));  vis[0] = true;  ans.clear();  vector<int> next;  next.push_back(0);  for(int i = 0; i < d[0]; i++) {    int min_color = INF;    for(int j = 0; j < next.size(); j++) {      int u = next[j];      for(int k = 0; k < G[u].size(); k++) {        int e = G[u][k];        int v = edges[e].v;        if(d[u] == d[v] + 1)          min_color = min(min_color, edges[e].c);      }    }    ans.push_back(min_color);    // find out the next vertices of the next phase    vector<int> next2;     for(int j = 0; j < next.size(); j++) {      int u = next[j];      for(int k = 0; k < G[u].size(); k++) {        int e = G[u][k];        int v = edges[e].v;        if(d[u] == d[v] + 1 && !vis[v] && edges[e].c == min_color) {          vis[v] = true;          next2.push_back(v);        }      }    }    next = next2;  }  printf("%d\n", ans.size());  printf("%d", ans[0]);  for(int i = 1; i < ans.size(); i++) printf(" %d", ans[i]);  printf("\n");}int main() {  int u, v, c, m;  while(scanf("%d%d", &n, &m) == 2) {    for(int i = 0; i < n; i++) G[i].clear();    while(m--) {      scanf("%d%d%d", &u, &v, &c);      AddEdge(u-1, v-1, c);      AddEdge(v-1, u-1, c);    }    rev_bfs();    bfs();  }  return 0;}