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)的更多相关文章

  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. effective c++ 条款6 如果不想要就要告诉大家

    这个条款应该和第五个放在一起 编译器默认生成 1 无参构造函数, 2 析构函数 3 拷贝构造函数 4 赋值预算符 当我们不需要,就要显示的告诉大家我们不需要. 方法:自己声明这个函数为private, ...

  2. [WebGL入门]二十四,补色着色

    注:文章译自http://wgld.org/,原作者杉本雅広(doxas),文章中假设有我的额外说明,我会加上[lufy:],另外,鄙人webgl研究还不够深入,一些专业词语,假设翻译有误,欢迎大家指 ...

  3. 乐在其中设计模式(C#) - 访问者模式(Visitor Pattern)

    原文:乐在其中设计模式(C#) - 访问者模式(Visitor Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 访问者模式(Visitor Pattern) 作者:webabc ...

  4. 玩转Web之easyui(二)-----easy ui 异步加载生成树节点(Tree),点击树生成tab(选项卡)

    关于easy ui 异步加载生成树及点击树生成选项卡,这里直接给出代码,重点部分代码中均有注释 前台: $('#tree').tree({ url: '../servlet/School_Tree?i ...

  5. YT新人之巅峰大决战03

    题目链接 Problem Description Now give you two integers n m, you just tell me the m-th number after radix ...

  6. configure.ac:20: error: Autoconf version 2.65 or higher is required

    安装thrift例如,下面的问题出现: configure.ac:20: error: Autoconf version 2.65 or higher is required wget http:// ...

  7. Oracle 11G DataGuard生产环境又一次启动具体过程

     场景,重新启动数据库,不重新启动linux系统,所以不用考虑监听程序,#linux输入lsnrctl start1 数据库关闭1.1 关闭主库SHUTDOWN IMMEDIATE; SQL> ...

  8. 【原创】构建高性能ASP.NET站点之三 细节决定成败

    原文:[原创]构建高性能ASP.NET站点之三 细节决定成败 构建高性能ASP.NET站点之三 细节决定成败 前言:曾经就因为一个小小的疏忽,从而导致了服务器崩溃了,后来才发现:原来就是因为一个循环而 ...

  9. default argument given of parameter 的问题

    今天写了一个类,当中的一个方法用到了默认參数,结果报了  "default argument given of parameter 的问题 " 错误. 类头文件的声明例如以下: v ...

  10. poj 1274The Perfect Stall

    第一次接触二分图匹配. 这题是一个匈牙利算法的模板题直接套即可. 题意是  给你奶牛和谷仓的个数a和b,接下来a行是奶牛喜欢去的谷仓.第一个是谷仓个数,接下来是谷仓编号. 这里我们把行当奶牛,列当谷仓 ...