• UVa1048 Low Cost Air Travel——最短路


    很好的一道题呀

    思路

    状态(d(i,j))表示已经经过了行程单中的(i)个城市,目前在城市(j)的最小代价,直接建边跑最短路就行了
    比如机票为(ACBD),行程单为(CD),那么对于((0,A)),连向((1,C))((1,B))((2,D))
    有两个需要注意的地方
    1.起点为((1,行程单的起点))
    2.城市编号很大,要离散化
    以下是代码,离散化用(map)完成

    #include <algorithm>
    #include  <iostream>
    #include   <cstdlib>
    #include   <cstring>
    #include    <cstdio>
    #include    <string>
    #include    <vector>
    #include     <cmath>
    #include     <ctime>
    #include     <queue>
    #include       <map>
    #include       <set>
    
    using namespace std;
    
    #define ull unsigned long long
    #define pii pair<int, int>
    #define uint unsigned int
    #define mii map<int, int>
    #define lbd lower_bound
    #define ubd upper_bound
    #define INF 0x3f3f3f3f
    #define IINF 0x3f3f3f3f3f3f3f3fLL
    #define DEF 0x8f8f8f8f
    #define DDEF 0x8f8f8f8f8f8f8f8fLL
    #define vi vector<int>
    #define ll long long
    #define mp make_pair
    #define pb push_back
    #define re register
    #define il inline
    
    #define N 10000
    
    struct Edge {
      int next, from, to, w, id;
    }e[2000000];
    
    int ticketCnt, routeCnt, nodeCnt, cityCnt;
    int price[250], cities[250];
    vi tickets[250];
    map<pii, int> nodeId;
    mii cityId;
    pii originNode[N+5];
    int head[N+5], eid;
    int d[N+5], pre[N+5];
    bool inq[N+5];
    int stk[N+5], tp;
    queue<int> q;
    
    void addEdge(int u, int v, int w, int id) {
      e[++eid] = Edge{head[u], u, v, w, id};
      head[u] = eid;
    }
    
    void spfa() {
      memset(d, 0x3f, sizeof d);
      memset(inq, 0, sizeof inq);
      memset(pre, 0, sizeof pre);
      int S = nodeId[mp(1, cities[1])];
      d[S] = 0;
      q.push(S);
      while(!q.empty()) {
        int u = q.front(); q.pop();
        inq[u] = 0;
        for(int i = head[u]; i; i = e[i].next) {
          int v = e[i].to, w = e[i].w;
          if(d[v] > d[u]+w) {
            d[v] = d[u]+w;
            pre[v] = i;
            if(!inq[v]) inq[v] = 1, q.push(v);
          }
        }
      }
    }
    
    void mark(int u) {
      if(!pre[u]) return ;
      stk[++tp] = e[pre[u]].id;
      mark(e[pre[u]].from);
    }
    
    int main() {
      int kase = 0;
      while(~scanf("%d", &ticketCnt) && ticketCnt) {
        ++kase;
        nodeCnt = cityCnt = 0;
        nodeId.clear();
        cityId.clear();
        for(int i = 1, cnt; i <= ticketCnt; ++i) {
          scanf("%d%d", &price[i], &cnt);
          tickets[i].clear();
          for(int j = 1, x; j <= cnt; ++j) {
            scanf("%d", &x);
            if(!cityId.count(x)) cityId[x] = ++cityCnt;
            tickets[i].pb(cityId[x]);
          }
        }
        scanf("%d", &routeCnt);
        for(int t = 1, len; t <= routeCnt; ++t) {
          memset(head, 0, sizeof head);
          eid = 0;
          scanf("%d", &len);
          for(int c = 1; c <= len; ++c) {
            scanf("%d", &cities[c]);
            if(!cityId.count(cities[c])) cityId[cities[c]] = ++cityCnt;
            cities[c] = cityId[cities[c]];
          }
          for(int ticket = 1; ticket <= ticketCnt; ++ticket) {
            for(int i = cities[1] == tickets[ticket][0]; i <= len; ++i) {
              int cnt = i;
              pii cur = mp(i, tickets[ticket][0]);
              if(!nodeId.count(cur)) nodeId[cur] = ++nodeCnt, originNode[nodeCnt] = cur;
              for(int j = 1; j < tickets[ticket].size(); ++j) {
                if(cnt+1 <= len && cities[cnt+1] == tickets[ticket][j]) cnt++;
                pii newState = mp(cnt, tickets[ticket][j]);
                if(!nodeId.count(newState)) nodeId[newState] = ++nodeCnt, originNode[nodeCnt] = newState;
                addEdge(nodeId[cur], nodeId[newState], price[ticket], ticket);
              }
            }
          }
          spfa();
          printf("Case %d, Trip %d: Cost = %d
    ", kase, t, d[nodeId[mp(len, cities[len])]]);
          printf("  Tickets used: ");
          tp = 0;
          mark(nodeId[mp(len, cities[len])]);
          for(int i = tp; i > 1; --i) printf("%d ", stk[i]);
          printf("%d
    ", stk[1]);
        }
      }
      return 0;
    }
    
  • 相关阅读:
    WP8.1 UI 编程 四、图形
    分治法 全排列问题的一个Java实现
    合并排序算法时间复杂度分析
    js如何实现复制粘贴功能
    关于<meta name="applicable-device"content="pc">
    ready
    css文字强制大写输入
    关于input,button标签在苹果手机上显示阴影解决办法
    【C#】中用if判断值是否是否为空
    视频格式MP4,需要转码
  • 原文地址:https://www.cnblogs.com/dummyummy/p/10823762.html
Copyright © 2020-2023  润新知