zoukankan      html  css  js  c++  java
  • uva 1048 最短路的建图 (巧,精品)

    大白书 P341这题说的是给了NT种飞机票,给了价钱和整个途径,给了nI条要旅游的路线。使用飞机票都必须从头第一站开始坐,可以再这个路径上的任何一点下飞机一但下飞机了就不能再上飞机,只能重新买票,对于每张票使用的状态有经过了这个路途的前i个点使用它,那么点就有,n*len(n为城市编号,为旅途所经过的所有点的个数),每张票在已经走完第一个点使用,第二个点,第三个点使用。。。最后从经过第一个点的旅途开始地方跑最长路,直到跑了len 旅途结束的点。

    // LA3561 Low Cost Air Travel
    #include<cstdio>
    #include<cstring>
    #include<queue>
    #include<algorithm>
    using namespace std;
    
    const int INF = 1000000000;
    const int maxn = 4000 + 10;
    
    struct Edge {
      int from, to, dist, val;
    };
    
    struct HeapNode {
      int d, u;
      bool operator < (const HeapNode& rhs) const {
        return d > rhs.d;
      }
    };
    
    struct Dijkstra {
      int n, m;
      vector<Edge> edges;
      vector<int> G[maxn];
      bool done[maxn];    // 是否已永久标号
      int d[maxn];        // s到各个点的距离
      int p[maxn];        // 最短路中的上一条弧
    
      void init(int n) {
        this->n = n;
        for(int i = 0; i < n; i++) G[i].clear();
        edges.clear();
      }
    
      void AddEdge(int from, int to, int dist, int val) {
        edges.push_back((Edge){from, to, dist, val});
        m = edges.size();
        G[from].push_back(m-1);
      }
    
      void dijkstra(int s) {
        priority_queue<HeapNode> Q;
        for(int i = 0; i < n; i++) d[i] = INF;
        d[s] = 0;
        memset(done, 0, sizeof(done));
        Q.push((HeapNode){0, s});
        while(!Q.empty()) {
          HeapNode x = Q.top(); Q.pop();
          int u = x.u;
          if(done[u]) continue;
          done[u] = true;
          for(int i = 0; i < G[u].size(); i++) {
            Edge& e = edges[G[u][i]];
            if(d[e.to] > d[u] + e.dist) {
              d[e.to] = d[u] + e.dist;
              p[e.to] = G[u][i];
              Q.push((HeapNode){d[e.to], e.to});
            }
          }
        }
      }
    
      vector<int> GetShortestPath(int s, int t) {
        vector<int> path;
        while(t != s) {
          path.push_back(edges[p[t]].val);
          t = edges[p[t]].from;
        }
        reverse(path.begin(), path.end());
        return path;
      }
    };
    
    //////// 题目相关
    #include<map>
    
    int n_cities;
    map<int,int> city_id;
    
    int ID(int city) {
      if(city_id.count(city)) return city_id[city];
      city_id[city] = n_cities++;
      return n_cities-1;
    }
    
    int ID(int visited, int cur) { return (visited-1) * n_cities + cur; }
    
    const int maxnt = 100;
    int cost[maxnt];
    vector<int> cities[maxnt], iti;
    
    Dijkstra solver;
    
    int main() {
      int NT, NI, x, len, kase = 0;
      while(scanf("%d", &NT) == 1 && NT) {
        n_cities = 0;
        city_id.clear();
        for(int i = 0; i < NT; i++) {
          cities[i].clear();
          scanf("%d%d", &cost[i], &len);
          while(len--) { scanf("%d", &x); cities[i].push_back(ID(x)); }
        }
        scanf("%d", &NI);
        kase++;
        for(int trip = 1; trip <= NI; trip++) {
          iti.clear();
          scanf("%d", &len);
          for(int i = 0; i < len; i++) { scanf("%d", &x); iti.push_back(ID(x)); }
    
          solver.init(n_cities * len);
          for(int ticket = 0; ticket < NT; ticket++)
            for(int visited = 1; visited < len; visited++) {
              int cur = cities[ticket][0]; // 当前状态为(visited, cur)
              int next = visited;          // 下一个需要访问的城市在iti中的下标
              for(int leg = 1; leg < cities[ticket].size(); leg++) { // 使用前leg段
                if(cities[ticket][leg] == iti[next]) next++; // 行程上多经过一个城市
                solver.AddEdge(ID(visited, cur), ID(next, cities[ticket][leg]), cost[ticket], ticket+1);
                if(next == len) break; // 行程单已经走完
              }
            }
          int src = ID(1, iti[0]), dest = ID(len, iti[len-1]);
          solver.dijkstra(src);
          printf("Case %d, Trip %d: Cost = %d
    ", kase, trip, solver.d[dest]);
          printf("  Tickets used:");
          vector<int> path = solver.GetShortestPath(src, dest);
          for(int i = 0; i < path.size(); i++) printf(" %d", path[i]);
          printf("
    ");
        }
      }
      return 0;
    }
  • 相关阅读:
    滚屏到相应位置才加载图片
    cs文件编译成dll文件
    SPAM搜索引擎垃圾技术
    新HTML元素:Canonical Link(权威链接),解决网络复制内容
    Asp.Net 文件操作基类(读取,删除,批量拷贝,删除,写入,获取文件夹大小,文件属性,遍历目录)
    VS2005发布网站项目时整个站点生成为一个自定义名称的dll文件
    301转向代码合集
    区别不同浏览器,CSS hack写法
    教你识别交换购买友情链接里的八种骗局真相!
    C#中Cookies的存取
  • 原文地址:https://www.cnblogs.com/Opaser/p/4358346.html
Copyright © 2011-2022 走看看