POJ 3013 Big Christmas Tree(最短路Dijkstra+优先队列优化,SPFA)

ACM

题目地址:POJ 3013

题意: 

圣诞树是由n个节点和e个边构成的,点编号1-n。树根为编号1,选择一些边。使得全部节点构成一棵树。选择边的代价是(子孙的点的重量)×(这条边的价值)。

求代价最小多少。

分析: 

单看每一个点被计算过的代价,非常明显就是从根到节点的边的价值。所以这是个简单的单源最短路问题。

只是坑点还是非常多的。

点的数量高达5w个,用矩阵存不行。仅仅能用边存。 

还有路径和结果会超int。所以要提高INF的上限。(1<<16)*50000就可以。

能够用Dijkstra+优先队列做,也能够用SPFA做,貌似SPFA会更快。我这里用的是Dijkstra,要1s多...回头要用SPFA做一遍。

用SPFA做了一遍发现也是1s多,看了是STL用多了 = =。 

嘛。留个模板。

代码: 

(Dijkstra+priority_queue)

  1. /*
  2. * Author: illuz <iilluzen[at]gmail.com>
  3. * File: 3013.cpp
  4. * Create Date: 2014-07-27 09:54:35
  5. * Descripton: dijkstra
  6. */
  7.  
  8. #include <cstdio>
  9. #include <cstring>
  10. #include <iostream>
  11. #include <algorithm>
  12. using namespace std;
  13. #include <vector>
  14. #include <queue>
  15. #define repf(i,a,b) for(int i=(a);i<=(b);i++)
  16.  
  17. const int N = 50100;
  18. const long long INF = (long long)(1<<16)*N;
  19.  
  20. struct Edge {
  21. int from, to;
  22. int dist;
  23. };
  24.  
  25. struct HeapNode {
  26. int d;
  27. int u;
  28. bool operator < (const HeapNode rhs) const {
  29. return d > rhs.d;
  30. }
  31. };
  32.  
  33. struct Dijkstra {
  34. int n, m; // number of nodes and edges
  35. vector<Edge> edges;
  36. vector<int> G[N]; // graph
  37. bool vis[N]; // visited?
  38.  
  39. long long d[N]; // dis
  40. int p[N]; // prevent edge
  41.  
  42. void init(int _n) {
  43. n = _n;
  44. }
  45.  
  46. void relief() {
  47. for (int i = 0; i < n; i++) {
  48. G[i].clear();
  49. }
  50. edges.clear();
  51. }
  52.  
  53. void AddEdge(int from, int to, int dist) {
  54. // if non-directed, add twice
  55. edges.push_back((Edge){from, to, dist});
  56. m = edges.size();
  57. G[from].push_back(m - 1);
  58. }
  59.  
  60. void dijkstra(int s) {
  61. priority_queue<HeapNode> Q;
  62. for (int i = 0; i < n; i++) {
  63. d[i] = INF;
  64. vis[i] = 0;
  65. }
  66. d[s] = 0;
  67.  
  68. Q.push((HeapNode){0, s});
  69. while (!Q.empty()) {
  70. HeapNode x = Q.top();
  71. Q.pop();
  72. int u = x.u;
  73. if (vis[u]) {
  74. continue;
  75. }
  76. vis[u] = true;
  77. for (int i = 0; i < G[u].size(); i++) { // update the u's linking nodes
  78. Edge& e = edges[G[u][i]]; //ref for convenient
  79. if (d[e.to] > d[u] + e.dist) {
  80. d[e.to] = d[u] + e.dist;
  81. p[e.to] = G[u][i];
  82. Q.push((HeapNode){d[e.to], e.to});
  83. }
  84. }
  85. }
  86. }
  87. };
  88.  
  89. int t;
  90. int e, v, x, y, d, w[N];
  91.  
  92. int main() {
  93. scanf("%d", &t);
  94. Dijkstra di;
  95.  
  96. while (t--) {
  97. scanf("%d%d", &v, &e);
  98. di.init(v);
  99.  
  100. repf (i, 0, v - 1) {
  101. scanf("%d" ,&w[i]);
  102. }
  103. repf (i, 0, e - 1) {
  104. scanf("%d%d%d", &x, &y, &d);
  105. di.AddEdge(x - 1, y - 1, d);
  106. di.AddEdge(y - 1, x - 1, d);
  107. }
  108. di.dijkstra(0);
  109.  
  110. long long ans = 0;
  111. bool ring = false;
  112. repf (i, 0, v - 1) {
  113. if (di.d[i] == INF) {
  114. ring = true;
  115. }
  116. ans += w[i] * di.d[i];
  117. }
  118. if (ring) {
  119. cout << "No Answer" << endl;
  120. } else {
  121. cout << ans << endl;
  122. }
  123.  
  124. if (t) // if not the last case
  125. di.relief();
  126. }
  127. return 0;
  128. }

(SPFA)

  1. /*
  2. * Author: illuz <iilluzen[at]gmail.com>
  3. * File: 3013_spfa.cpp
  4. * Create Date: 2014-07-27 15:44:45
  5. * Descripton: spfa
  6. */
  7.  
  8. #include <cstdio>
  9. #include <cstring>
  10. #include <iostream>
  11. #include <algorithm>
  12. using namespace std;
  13. #include <vector>
  14. #include <queue>
  15. #define repf(i,a,b) for(int i=(a);i<=(b);i++)
  16.  
  17. const int N = 50100;
  18. const long long INF = (long long)(1<<16)*N;
  19.  
  20. struct Edge {
  21. int from, to;
  22. int spst;
  23. };
  24.  
  25. struct SPFA {
  26. int n, m;
  27. vector<Edge> edges;
  28. vector<int> G[N]; // the edges which from i
  29. bool vis[N];
  30. long long d[N]; // sps
  31. int p[N]; // prevent
  32.  
  33. void init(int _n) {
  34. n = _n;
  35. }
  36.  
  37. void relief() {
  38. for (int i = 0; i < n; i++)
  39. G[i].clear();
  40. edges.clear();
  41. }
  42.  
  43. void AddEdge(int from, int to, int spst) {
  44. // if non-sprected, add twice
  45. edges.push_back((Edge){from, to, spst});
  46. m = edges.size();
  47. G[from].push_back(m - 1);
  48. }
  49.  
  50. void spfa(int s) {
  51. queue<int> Q;
  52. while (!Q.empty())
  53. Q.pop();
  54. for (int i = 0; i < n; i++) {
  55. d[i] = INF;
  56. vis[i] = 0;
  57. }
  58. d[s] = 0;
  59. vis[s] = 1;
  60. Q.push(s);
  61. while (!Q.empty()) {
  62. int u = Q.front();
  63. Q.pop();
  64. vis[u] = 0;
  65. for (int i = 0; i < G[u].size(); i++) {
  66. Edge& e = edges[G[u][i]];
  67. if (d[e.to] > d[u] + e.spst) {
  68. d[e.to] = d[u] + e.spst;
  69. p[e.to] = G[u][i];
  70. if (!vis[e.to]) {
  71. vis[e.to] = 1;
  72. Q.push(e.to);
  73. }
  74. }
  75. }
  76. }
  77.  
  78. }
  79. };
  80.  
  81. int t;
  82. int e, v, x, y, d, w[N];
  83.  
  84. int main() {
  85. scanf("%d", &t);
  86. SPFA sp;
  87.  
  88. while (t--) {
  89. scanf("%d%d", &v, &e);
  90. sp.init(v);
  91.  
  92. repf (i, 0, v - 1) {
  93. scanf("%d" ,&w[i]);
  94. }
  95. repf (i, 0, e - 1) {
  96. scanf("%d%d%d", &x, &y, &d);
  97. sp.AddEdge(x - 1, y - 1, d);
  98. sp.AddEdge(y - 1, x - 1, d);
  99. }
  100. sp.spfa(0);
  101.  
  102. long long ans = 0;
  103. bool ring = false;
  104. repf (i, 0, v - 1) {
  105. if (sp.d[i] == INF) {
  106. ring = true;
  107. }
  108. ans += w[i] * sp.d[i];
  109. }
  110. if (ring) {
  111. cout << "No Answer" << endl;
  112. } else {
  113. cout << ans << endl;
  114. }
  115.  
  116. if (t) // if not the last case
  117. sp.relief();
  118. }
  119. return 0;
  120. }

版权声明:本文博主原创文章。博客,未经同意不得转载。

POJ 3013 Big Christmas Tree(最短Dijkstra+优先级队列优化,SPFA)的更多相关文章

  1. poj 3013 Big Christmas Tree (最短路径Dijsktra) -- 第一次用优先队列写Dijsktra

    http://poj.org/problem?id=3013 Big Christmas Tree Time Limit: 3000MS   Memory Limit: 131072K Total S ...

  2. SPFA/Dijkstra POJ 3013 Big Christmas Tree

    题目传送门 题意:找一棵树使得造价最少,造价为每个点的子节点造价和*边的造价和 分析:最短路跑出1根节点到每个点的最短边权值,然后每个点的权值*最短边距和就是答案,注意INF开足够大,n<=1特 ...

  3. poj 3013 Big Christmas Tree

    Big Christmas Tree Time Limit: 3000MS   Memory Limit: 131072K Total Submissions: 20974   Accepted: 4 ...

  4. poj 3013 Big Christmas Tree Djistra

    Big Christmas Tree 题意:图中每个节点和边都有权值,图中找出一颗树,树根为1使得 Σ(树中的节点到树根的距离)*(以该节点为子树的所有节点的权值之和) 结果最小: 分析:直接求出每个 ...

  5. poj 3013 Big Christmas Tree (dij+优先级队列优化 求最短)

    模板 意甲冠军:给你一个图,1始终根,每一方都有单价值,每个点都有权重新. 每个边缘的价格值 = sum(后继结点重)*单价方值. 最低价格要求树值,它构成了一棵树n-1条边的最小价值. 算法: 1. ...

  6. 【POJ】2373 Dividing the Path(单调队列优化dp)

    题目 传送门:QWQ 分析 听说是水题,但还是没想出来. $ dp[i] $为$ [1,i] $的需要的喷头数量. 那么$ dp[i]=min(dp[j])+1 $其中$ j<i $ 这是个$ ...

  7. POJ Big Christmas Tree(最短的基础)

    Big Christmas Tree 题目分析: 叫你构造一颗圣诞树,使得 (sum of weights of all descendant nodes) × (unit price of the ...

  8. POJ3013 Big Christmas Tree[转换 最短路]

    Big Christmas Tree Time Limit: 3000MS   Memory Limit: 131072K Total Submissions: 23387   Accepted: 5 ...

  9. POJ 3013 SPFA算法,邻接表的使用

    Big Christmas Tree Time Limit: 3000MS   Memory Limit: 131072K Total Submissions: 19029   Accepted: 4 ...

随机推荐

  1. C# 几种方法来复制的阵列

    突然接触到,所以就写一下共享. 首先说明一下,数组是引用类型的,所以注意不要在复制时复制了地址而没有复制数值! 事实上在复制数组的时候.一定要用new在堆中开辟一块新的空间专门用于存放数组.这样才是有 ...

  2. Java 将字节数组转化为16进制的多种方案

    很多时候我们需要将字节数组转化为16进制字符串来保存,尤其在很多加密的场景中,例如保存密钥等.因为字节数组,除了写入文件或者以二进制的形式写入数据库以外,无法直接转为为字符串,因为字符串结尾有\0,当 ...

  3. COJ 1102 - You Can Say 11 题解

    本题就是给出一个无穷大数,算其能否被11除尽 Description Your job is, given a positive number N, determine if it is a mult ...

  4. 乐在其中设计模式(C#) - 迭代器模式(Iterator Pattern)

    原文:乐在其中设计模式(C#) - 迭代器模式(Iterator Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 迭代器模式(Iterator Pattern) 作者:weba ...

  5. 360的IM可能会是什么样?

    尽管周鸿祎不止一次的说过,它不会进入IM领域,可是在360和QQ大战之后,很多用户 在卸载了QQ,寻找替代的IM工具的时候,发现他们非常难找到合适的替代IM工具,由于 好友非常难迁移.在用户的强烈 呼 ...

  6. 【Web探索之旅】第二部分第四课:数据库

    内容简介 1.第二部分第四课:数据库 2.第二部分第五课预告:响应式网站 第二部分第四课:数据库 说到“数据库”,顾名思义,是“数据的仓库”的意思. 所以数据库的一大作用就是储存数据咯. 为什么Web ...

  7. [LeetCode92]Reverse Linked List II

    题目: Reverse a linked list from position m to n. Do it in-place and in one-pass. For example:Given 1- ...

  8. CodeForces 22D Segments 排序水问题

    主题链接:点击打开链接 升序右键点.采取正确的点 删边暴力 #include <cstdio> #include <cstring> #include <algorith ...

  9. hdu 4856 Tunnels(bfs+状态压缩)

    题目链接:hdu 4856 Tunnels 题目大意:给定一张图,图上有M个管道,管道给定入口和出口,单向,如今有人想要体验下这M个管道,问最短须要移动的距离,起点未定. 解题思路:首先用bfs处理出 ...

  10. bitnami redmine 安装插件

    https://wiki.bitnami.com/Applications/BitNami_Redmine_Stack#How_to_install_a_plugin_on_Redmine.3f 版权 ...