传送门:POJ 3013 Big Christmas Tree

描述:
Big Christmas Tree
Time Limit: 3000MS   Memory Limit: 131072K
Total Submissions: 23338   Accepted: 5042

Description

Christmas is coming to KCM city. Suby the loyal civilian in KCM city is preparing a big neat Christmas tree. The simple structure of the tree is shown in right picture.

The tree can be represented as a collection of numbered nodes and some edges. The nodes are numbered 1 through n. The root is always numbered 1. Every node in the tree has its weight. The weights can be different from each other. Also the shape of every available edge between two nodes is different, so the unit price of each edge is different. Because of a technical difficulty, price of an edge will be (sum of weights of all descendant nodes) × (unit price of the edge).

Suby wants to minimize the cost of whole tree among all possible choices. Also he wants to use all nodes because he wants a large tree. So he decided to ask you for helping solve this task by find the minimum cost.

Input

The input consists of T test cases. The number of test cases T is given in the first line of the input file. Each test case consists of several lines. Two numbers v,e (0 ≤ ve ≤ 50000) are given in the first line of each test case. On the next line, v positive integers wi indicating the weights of v nodes are given in one line. On the following e lines, each line contain three positive integers abc indicating the edge which is able to connect two nodes a and b, and unit price c.

All numbers in input are less than 216.

Output

For each test case, output an integer indicating the minimum possible cost for the tree in one line. If there is no way to build a Christmas tree, print “No Answer” in one line.

Sample Input

2
2 1
1 1
1 2 15
7 7
200 10 20 30 40 50 60
1 2 1
2 3 3
2 4 2
3 5 4
3 7 2
3 6 3
1 5 9

Sample Output

15
1210

Source

POJ Monthly--2006.09.29, Kim, Chan Min (kcm1700@POJ)
题意:

给n个点从1到n标号,下面一行是每个点的权,另外给出m条边,下面是每条边的信息,两个端点+权值,边是无向边。你的任务是选出一些边,使这个图变成一棵树。这棵树的花费是这样算的,1号固定为树根,树中每个双亲节点下面的边都有个单价(即边权),然后单价乘上这条边的下面所有的子孙后代的点权和(看sample2,只要除掉边 1 5 9 按照这个方法就能算出1210)

思路:

把sample2用式子列一下就能发现,每个点的权都要乘上好几条边的权,是哪几条边呢,就是这个点回到点1的路径上的那些边

所以最后的树的花费可以写成  res = sum{  (点权) * (该点回到点1的路径的边权和)  } ,这些点是2到n,1是不用算的

所以决定这条式子大小的,只有  (该点回到点1的路径的边权和)  ,  只要能让它最小即可。  令到每个点回到点1的路径边权和最小是什么?就是最短路啊!

所以从点1运行一次最短路,就可以知道1到每个点的最短路(也就是每个点到点1的最短路,因为无向图)

但是要注意一个坑,没看清楚题意,超时了很多次,就是点数可能为0(太坑了),点数为0运行不了最短路一直卡在里面,所以特判一下,输出0,如果点数1同样也是0的,因为整个树不会有边

还要注意用long long,写代码的太急了,直接套模板就没改数据类型,WA了好几发_(:зゝ∠)_

另外注意网上的各种说法

1.有人说dij过不了,是能过的

2.有人说dij要手写heap才能过,直接用STL的优先队列也是能过的

3.spfa能过

4.用vector可以建图,建议不要,确实效率不太高,毕竟点很多。下面就给出两个不同建图方式的代码

代码一:

(vector建图)

//G++ 2516ms  4760k
#include <iostream>
#include <cstdio>
#include <cstring>
#include<vector>
#include<queue>
#define ll __int64
using  namespace std;/*vector建图点很多的话效率会比较低
*/
const ll inf= 0x3f3f3f3f3f3f3f3fLL;
const  int  maxn=50010;
vector<pair<int,int> >E[maxn];//邻接表
ll d[maxn];
bool done[maxn];
int val[maxn];
int v,e;void  init(){for(int i=0; i<maxn; i++)E[i].clear();for(int i=0; i<maxn; i++)done[i]=false;for(int i=0; i<maxn; i++)d[i]=inf;
}ll dijkstra(int s,int t){priority_queue<pair<ll,int> >q;int cnt=0;ll res=0;d[s]=0;q.push(make_pair(-d[s],s));//优队返回的是最大值,取负就返回的最小值while(!q.empty()){int now=q.top().second;q.pop();if(done[now]) continue;done[now]=true;cnt++;res+=d[now]*val[now];for(int i=0; i<E[now].size(); i++){int  v=E[now][i].first;if(d[v]>d[now]+E[now][i].second){d[v]=d[now]+E[now][i].second;q.push(make_pair(-d[v],v));}}}if(cnt<v) return -1;else return res;//熟悉heap+dij的本质,可以在dij过程中就统计出所有点的最短路和并乘上他们的权//不需要dij结束后去扫描一次所有点来计算,并且可以在dij过程判断是否能构成一棵树
}int  main(){int T;scanf("%d",&T);while(T--){init();scanf("%d%d",&v,&e);for(int i=1; i<=v; i++)scanf("%d",&val[i]);for(int i=1; i<=e; i++){int x,y,z;scanf("%d %d %d",&x,&y,&z);E[x].push_back(make_pair(y,z));  //边x,y,边权zE[y].push_back(make_pair(x,z));}if(v == 0 || v == 1){ //注意这个坑,会超时,出现n=0点的时候printf("0\n");continue;}ll ans=dijkstra(1, v);if(ans != -1)printf("%I64d\n",ans);else puts("No Answer");}return  0;
}
代码二:

显然这种不用vector建图效率更高

//G++ 594ms 3076k
#include <iostream>
#include <cstdio>
#include <queue>
#include <algorithm>
#include <cstring>
#define ll __int64
using  namespace std;/*结构体建图*tol记得初始化*/
const int N = 50010;
const ll inf= 0x3f3f3f3f3f3f3f3fLL;
int n,m,tol;
ll d[N];
int head[N];
bool done[N];
int val[N];
struct edge{int u,v,w,next;
}e[2*N];
typedef pair<ll,int>P;
priority_queue<P, vector<P>, greater<P> > q;//取最小值void add(int u,int v,int w){e[tol].u=u; e[tol].v=v; e[tol].w=w;e[tol].next=head[u]; head[u]=tol++;u=u^v;  v=u^v;  u=u^v;//异或e[tol].u=u; e[tol].v=v; e[tol].w=w;e[tol].next=head[u]; head[u]=tol++;
}ll Dij(){int cnt=0;ll res=0;d[1]=0;q.push(make_pair(d[1], 1));while(!q.empty()){int u,v,w;P x=q.top();q.pop();u=x.second;if(done[u]) continue;done[u]=true;cnt++;res+=d[u]*val[u];for(int i=head[u]; i!=-1; i=e[i].next){v=e[i].v;w=e[i].w;if(d[u]+w<d[v]){d[v]=d[u]+w;q.push(make_pair(d[v], v));}}}if(cnt<n) return -1;else return res;
}int main(){int T;scanf("%d",&T);while(T--){scanf("%d%d",&n,&m);for(int i=1; i<=n; i++)scanf("%d",&val[i]);while(!q.empty()) q.pop();tol=0;for(int i=1; i<=n; i++){head[i]=-1;d[i]=inf;done[i]=false;}for(int i=1; i<=m; i++){int u,v,w;scanf("%d%d%d",&u,&v,&w);add(u,v,w);}if(n == 0 || n == 1){ //注意这个坑,会超时,出现n=0点的时候printf("0\n");continue;}ll ans=Dij();if(ans != -1) printf("%I64d\n",ans);else printf("No Answer\n");}return 0;
}

poj 3013 Big Christmas Tree(最短路变形)相关推荐

  1. PKU 3013 Big Christmas Tree 最短路 spfa

    题意/Description:     Christmas is coming to KCM city. Suby the loyal civilian in KCM city is preparin ...

  2. poj 2263 最短路变形——最小边的最大值

    文章目录 本题:最短路变形--最小边的最大值 最短路变形--最大边的最小值 本题:最短路变形--最小边的最大值 最短路变形--最大边的最小值 poj2253

  3. poj 2253 最短路变形——最大边的最小值

    文章目录 本题:最短路变形--最大边的最小值 最短路变形--最小边的最大值 本题:最短路变形--最大边的最小值 题意: 给出两只青蛙.以及其他石头的坐标,需要求出可以到达另一只青蛙的所有路径中,青蛙跳 ...

  4. POJ-3013: Big Christmas Tree(dij,spfa)

    POJ-3013: Big Christmas Tree 题目链接:POJ:3013 Description Christmas is coming to KCM city. Suby the loy ...

  5. POJ 2054 Color a Tree (贪心)

    $ POJ~2054~Color~a~Tree $ $ solution: $ 我们先从题中抽取信息,因为每个点的费用和染色的次数有关,所以我们可以很自然的想到先给权值大的节点染色.但是题目还说每个节 ...

  6. Russian Dolls on the Christmas Tree

    题目链接:Russian Dolls on the Christmas Tree 显然可以dfs序转区间之后上莫队,不过感觉会被卡. 其实也可以dfs序之后,对询问区间排序,然后线段树. 我懒得dfs ...

  7. 【图论-最短路变形】想越狱的小杉

    [图论-最短路变形]想越狱的小杉 Time Limit:1000MS  Memory Limit:65536K Description 背景 Background 这次小杉来到了经典美剧<越狱& ...

  8. poj 1797(最短路变形)

    题目链接:http://poj.org/problem?id=1797 思路:题目意思很简单,n个顶点,m条路,每条路上都有最大载重限制,问1->n最大载重量.其实就是一最短路的变形,定义wei ...

  9. POJ 1797 Heavy Transportation 最短路变形(dijkstra算法)

    题目:click here 题意: 有n个城市,m条道路,在每条道路上有一个承载量,现在要求从1到n城市最大承载量,而最大承载量就是从城市1到城市n所有通路上的最大承载量. 分析: 其实这个求最大边可 ...

最新文章

  1. 别再写 main 方法测试了,太 Low!这才是专业 Java 测试方法!
  2. Javascript 未结束的字符串常量
  3. .从三层架构到MVC,MVP
  4. VTK:可视化之Kitchen
  5. ORACLE数据库在导入导出时序列不一致的问题
  6. 注意指针修饰符的准确含义
  7. 信用算力基于 RocketMQ 实现金融级数据服务的实践
  8. java checkbox数组_Java中的复选框数组
  9. Fix Backup Database is terminating abnormally When performing a Farm Backup
  10. MacOS磁盘工具:如何将“校验和..“添加到磁盘映像
  11. 咱也过个双 11 !Flink Forward Asia 培训门票买一赠一!
  12. java rsa2加密算法_java RSA加密解密
  13. 全国计算机二级c真题及答案,全国计算机二级c语言历年真题及答案
  14. Hydra暴力破解smb协议(Windows用户名和密码)
  15. kettle执行sql语句错误总结
  16. 17-【istio】-【流量管理】-【流量管理案例篇】针对TCP流量
  17. 牛客练习赛73 遥远的记忆(理解)
  18. Window c++ 创建子进程
  19. HD1096 between “ 之间” 的含义
  20. 计算机主板结构分为at,2.2.1 计算机主板结构(1)

热门文章

  1. 传统安防实体店如何成功转型
  2. java课程设计指导记录表_JAVA课程设计指导书ofr2012级.doc
  3. matlab振动方程,数理方程关于振动方程的分析matlab.doc
  4. 社区小程序源码-带后台
  5. 解决USB3.0接口传输速度慢的问题
  6. 第三次自考总结——时间管理和学习知识
  7. 《我在风衣里藏了把刀》—— 转
  8. 凸包+凹包+凸边凹化算法
  9. 【Python】数据探索分析——东北大学软件学院大数据班数据挖掘实训一(1)
  10. 计算机发现到发展,发现计算机的“前世今生”