ZOJ 3946 Highway Project 贪心+最短路

题目链接:

http://www.icpc.moe/onlinejudge/showProblem.do?problemCode=3946

题解:

用dijkstra跑单元最短路径,如果对于顶点v,存在一系列边(ui,v)使得dis[v]最小(dis[v]表示0到v的距离)。这些边能且只能选一条,那么我们自然应该选cost最小的那个边了。

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<vector>
  5 #include<algorithm>
  6 #include<queue>
  7 using namespace std;
  8 
  9 typedef long long LL;
 10 const int maxn = 1e5 + 10;
 11 
 12 struct Edge {
 13     int ne, u, v, c, d;
 14     Edge(int ne, int u, int v, int d, int c) :ne(ne), u(u), v(v), d(d), c(c) {}
 15     Edge() {}
 16 }egs[maxn * 2];
 17 
 18 struct Heap {
 19     int u, d, c;
 20     Heap(int u, int d) :u(u), d(d) {}
 21     Heap() {}
 22     bool operator < (const Heap& tmp) const {
 23         return d>tmp.d;
 24     }
 25 };
 26 
 27 struct Node {
 28     int u, v, w;
 29     bool operator < (const Node& tmp) const {
 30         return w<tmp.w;
 31     }
 32 }nds[maxn];
 33 
 34 
 35 int head[maxn], tot;
 36 
 37 void addEdge(int u, int v, int d, int c) {
 38     egs[tot] = Edge(head[u], u, v, d, c);
 39     head[u] = tot++;
 40 }
 41 
 42 int n, m;
 43 LL ans_d, ans_c;
 44 
 45 LL dis[maxn];
 46 //pre[u]记录u和前驱节点的那条边的cost
 47 int pre[maxn];
 48 bool done[maxn];
 49 
 50 
 51 void dij() {
 52     for (int i = 0; i<n; i++) {
 53         dis[i] = 2e10;
 54     }
 55     memset(done, false, sizeof(done));
 56     priority_queue<Heap> pq;
 57     dis[0] = 0;
 58     pq.push(Heap(0, 0));
 59     while (!pq.empty()) {
 60         Heap x = pq.top(); pq.pop();
 61         int u = x.u;
 62         if (done[u]) continue;
 63         done[u] = true;
 64         int p = head[u];
 65         while (p != -1) {
 66             Edge &e = egs[p];
 67             if (dis[e.v]>dis[u] + e.d) {
 68                 dis[e.v] = dis[u] + e.d;
 69                 pre[e.v] = e.c;
 70                 pq.push(Heap(e.v, dis[e.v]));
 71             }
 72             else if (dis[e.v] == dis[u] + e.d) {
 73                 //这里贪心选cost最小的边
 74                 if (pre[e.v]>e.c)
 75                     pre[e.v] = e.c;
 76             }
 77             p = e.ne;
 78         }
 79     }
 80     ans_d = 0; ans_c = 0;
 81     for (int i = 0; i<n; i++) {
 82         ans_d += dis[i];
 83     }
 84     for (int i = 1; i<n; i++) {
 85         ans_c += pre[i];
 86     }
 87 }
 88 
 89 void init() {
 90     memset(head, -1, sizeof(head));
 91     memset(pre, -1, sizeof(pre));
 92     tot = 0;
 93 }
 94 
 95 int main() {
 96     //    freopen("data_in.txt","r",stdin);
 97     int tc;
 98     scanf("%d", &tc);
 99     while (tc--) {
100         scanf("%d%d", &n, &m);
101         init();
102         for (int i = 0; i<m; i++) {
103             int u, v, d, c;
104             scanf("%d%d%d%d", &u, &v, &d, &c);
105             addEdge(u, v, d, c);
106             addEdge(v, u, d, c);
107         }
108         dij();
109         printf("%lld %lld\n", ans_d, ans_c);
110     }
111     return 0;
112 }

 

posted @ 2016-05-07 22:41  fenicnn  阅读(212)  评论(0编辑  收藏  举报