POJ 3013 Big Christmas Tree(最短Dijkstra+优先级队列优化,SPFA)
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)
- /*
- * Author: illuz <iilluzen[at]gmail.com>
- * File: 3013.cpp
- * Create Date: 2014-07-27 09:54:35
- * Descripton: dijkstra
- */
- #include <cstdio>
- #include <cstring>
- #include <iostream>
- #include <algorithm>
- using namespace std;
- #include <vector>
- #include <queue>
- #define repf(i,a,b) for(int i=(a);i<=(b);i++)
- const int N = 50100;
- const long long INF = (long long)(1<<16)*N;
- struct Edge {
- int from, to;
- int dist;
- };
- struct HeapNode {
- int d;
- int u;
- bool operator < (const HeapNode rhs) const {
- return d > rhs.d;
- }
- };
- struct Dijkstra {
- int n, m; // number of nodes and edges
- vector<Edge> edges;
- vector<int> G[N]; // graph
- bool vis[N]; // visited?
- long long d[N]; // dis
- int p[N]; // prevent edge
- void init(int _n) {
- n = _n;
- }
- void relief() {
- for (int i = 0; i < n; i++) {
- G[i].clear();
- }
- edges.clear();
- }
- void AddEdge(int from, int to, int dist) {
- // if non-directed, add twice
- edges.push_back((Edge){from, to, dist});
- 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;
- vis[i] = 0;
- }
- d[s] = 0;
- Q.push((HeapNode){0, s});
- while (!Q.empty()) {
- HeapNode x = Q.top();
- Q.pop();
- int u = x.u;
- if (vis[u]) {
- continue;
- }
- vis[u] = true;
- for (int i = 0; i < G[u].size(); i++) { // update the u's linking nodes
- Edge& e = edges[G[u][i]]; //ref for convenient
- 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});
- }
- }
- }
- }
- };
- int t;
- int e, v, x, y, d, w[N];
- int main() {
- scanf("%d", &t);
- Dijkstra di;
- while (t--) {
- scanf("%d%d", &v, &e);
- di.init(v);
- repf (i, 0, v - 1) {
- scanf("%d" ,&w[i]);
- }
- repf (i, 0, e - 1) {
- scanf("%d%d%d", &x, &y, &d);
- di.AddEdge(x - 1, y - 1, d);
- di.AddEdge(y - 1, x - 1, d);
- }
- di.dijkstra(0);
- long long ans = 0;
- bool ring = false;
- repf (i, 0, v - 1) {
- if (di.d[i] == INF) {
- ring = true;
- }
- ans += w[i] * di.d[i];
- }
- if (ring) {
- cout << "No Answer" << endl;
- } else {
- cout << ans << endl;
- }
- if (t) // if not the last case
- di.relief();
- }
- return 0;
- }
(SPFA)
- /*
- * Author: illuz <iilluzen[at]gmail.com>
- * File: 3013_spfa.cpp
- * Create Date: 2014-07-27 15:44:45
- * Descripton: spfa
- */
- #include <cstdio>
- #include <cstring>
- #include <iostream>
- #include <algorithm>
- using namespace std;
- #include <vector>
- #include <queue>
- #define repf(i,a,b) for(int i=(a);i<=(b);i++)
- const int N = 50100;
- const long long INF = (long long)(1<<16)*N;
- struct Edge {
- int from, to;
- int spst;
- };
- struct SPFA {
- int n, m;
- vector<Edge> edges;
- vector<int> G[N]; // the edges which from i
- bool vis[N];
- long long d[N]; // sps
- int p[N]; // prevent
- void init(int _n) {
- n = _n;
- }
- void relief() {
- for (int i = 0; i < n; i++)
- G[i].clear();
- edges.clear();
- }
- void AddEdge(int from, int to, int spst) {
- // if non-sprected, add twice
- edges.push_back((Edge){from, to, spst});
- m = edges.size();
- G[from].push_back(m - 1);
- }
- void spfa(int s) {
- queue<int> Q;
- while (!Q.empty())
- Q.pop();
- for (int i = 0; i < n; i++) {
- d[i] = INF;
- vis[i] = 0;
- }
- d[s] = 0;
- vis[s] = 1;
- Q.push(s);
- while (!Q.empty()) {
- int u = Q.front();
- Q.pop();
- vis[u] = 0;
- for (int i = 0; i < G[u].size(); i++) {
- Edge& e = edges[G[u][i]];
- if (d[e.to] > d[u] + e.spst) {
- d[e.to] = d[u] + e.spst;
- p[e.to] = G[u][i];
- if (!vis[e.to]) {
- vis[e.to] = 1;
- Q.push(e.to);
- }
- }
- }
- }
- }
- };
- int t;
- int e, v, x, y, d, w[N];
- int main() {
- scanf("%d", &t);
- SPFA sp;
- while (t--) {
- scanf("%d%d", &v, &e);
- sp.init(v);
- repf (i, 0, v - 1) {
- scanf("%d" ,&w[i]);
- }
- repf (i, 0, e - 1) {
- scanf("%d%d%d", &x, &y, &d);
- sp.AddEdge(x - 1, y - 1, d);
- sp.AddEdge(y - 1, x - 1, d);
- }
- sp.spfa(0);
- long long ans = 0;
- bool ring = false;
- repf (i, 0, v - 1) {
- if (sp.d[i] == INF) {
- ring = true;
- }
- ans += w[i] * sp.d[i];
- }
- if (ring) {
- cout << "No Answer" << endl;
- } else {
- cout << ans << endl;
- }
- if (t) // if not the last case
- sp.relief();
- }
- return 0;
- }
版权声明:本文博主原创文章。博客,未经同意不得转载。
POJ 3013 Big Christmas Tree(最短Dijkstra+优先级队列优化,SPFA)的更多相关文章
- poj 3013 Big Christmas Tree (最短路径Dijsktra) -- 第一次用优先队列写Dijsktra
http://poj.org/problem?id=3013 Big Christmas Tree Time Limit: 3000MS Memory Limit: 131072K Total S ...
- SPFA/Dijkstra POJ 3013 Big Christmas Tree
题目传送门 题意:找一棵树使得造价最少,造价为每个点的子节点造价和*边的造价和 分析:最短路跑出1根节点到每个点的最短边权值,然后每个点的权值*最短边距和就是答案,注意INF开足够大,n<=1特 ...
- poj 3013 Big Christmas Tree
Big Christmas Tree Time Limit: 3000MS Memory Limit: 131072K Total Submissions: 20974 Accepted: 4 ...
- poj 3013 Big Christmas Tree Djistra
Big Christmas Tree 题意:图中每个节点和边都有权值,图中找出一颗树,树根为1使得 Σ(树中的节点到树根的距离)*(以该节点为子树的所有节点的权值之和) 结果最小: 分析:直接求出每个 ...
- poj 3013 Big Christmas Tree (dij+优先级队列优化 求最短)
模板 意甲冠军:给你一个图,1始终根,每一方都有单价值,每个点都有权重新. 每个边缘的价格值 = sum(后继结点重)*单价方值. 最低价格要求树值,它构成了一棵树n-1条边的最小价值. 算法: 1. ...
- 【POJ】2373 Dividing the Path(单调队列优化dp)
题目 传送门:QWQ 分析 听说是水题,但还是没想出来. $ dp[i] $为$ [1,i] $的需要的喷头数量. 那么$ dp[i]=min(dp[j])+1 $其中$ j<i $ 这是个$ ...
- POJ Big Christmas Tree(最短的基础)
Big Christmas Tree 题目分析: 叫你构造一颗圣诞树,使得 (sum of weights of all descendant nodes) × (unit price of the ...
- POJ3013 Big Christmas Tree[转换 最短路]
Big Christmas Tree Time Limit: 3000MS Memory Limit: 131072K Total Submissions: 23387 Accepted: 5 ...
- POJ 3013 SPFA算法,邻接表的使用
Big Christmas Tree Time Limit: 3000MS Memory Limit: 131072K Total Submissions: 19029 Accepted: 4 ...
随机推荐
- C# 几种方法来复制的阵列
突然接触到,所以就写一下共享. 首先说明一下,数组是引用类型的,所以注意不要在复制时复制了地址而没有复制数值! 事实上在复制数组的时候.一定要用new在堆中开辟一块新的空间专门用于存放数组.这样才是有 ...
- Java 将字节数组转化为16进制的多种方案
很多时候我们需要将字节数组转化为16进制字符串来保存,尤其在很多加密的场景中,例如保存密钥等.因为字节数组,除了写入文件或者以二进制的形式写入数据库以外,无法直接转为为字符串,因为字符串结尾有\0,当 ...
- COJ 1102 - You Can Say 11 题解
本题就是给出一个无穷大数,算其能否被11除尽 Description Your job is, given a positive number N, determine if it is a mult ...
- 乐在其中设计模式(C#) - 迭代器模式(Iterator Pattern)
原文:乐在其中设计模式(C#) - 迭代器模式(Iterator Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 迭代器模式(Iterator Pattern) 作者:weba ...
- 360的IM可能会是什么样?
尽管周鸿祎不止一次的说过,它不会进入IM领域,可是在360和QQ大战之后,很多用户 在卸载了QQ,寻找替代的IM工具的时候,发现他们非常难找到合适的替代IM工具,由于 好友非常难迁移.在用户的强烈 呼 ...
- 【Web探索之旅】第二部分第四课:数据库
内容简介 1.第二部分第四课:数据库 2.第二部分第五课预告:响应式网站 第二部分第四课:数据库 说到“数据库”,顾名思义,是“数据的仓库”的意思. 所以数据库的一大作用就是储存数据咯. 为什么Web ...
- [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- ...
- CodeForces 22D Segments 排序水问题
主题链接:点击打开链接 升序右键点.采取正确的点 删边暴力 #include <cstdio> #include <cstring> #include <algorith ...
- hdu 4856 Tunnels(bfs+状态压缩)
题目链接:hdu 4856 Tunnels 题目大意:给定一张图,图上有M个管道,管道给定入口和出口,单向,如今有人想要体验下这M个管道,问最短须要移动的距离,起点未定. 解题思路:首先用bfs处理出 ...
- bitnami redmine 安装插件
https://wiki.bitnami.com/Applications/BitNami_Redmine_Stack#How_to_install_a_plugin_on_Redmine.3f 版权 ...