poj-3013 透过现象看本质,其实都一样
来源:互联网 发布:python newspaper 编辑:程序博客网 时间:2024/05/19 04:02
这道题目咋一看就是最小生成树啊。
题目描述大概是这样:
KCm要准备一颗圣诞树,这棵树有一些节点和边组成。节点从1到n,根总是1.每个节点都有自己的总量,而边的价格是由边的单价乘以子孙节点的重量。
求出这么一颗有n个节点的树,使花费最小。
很像最小生成树,仔细研究,没法这样做。因为每条边在找到这颗树之前很难计算它的价值。
因为本来你算好的边的价值,但是在去掉某些边时,会导致边的价值发生变化,那怎么办。。。。
这道题目开始我也是不知道怎么计算,看到discuss说是最短路。试想最后已经得到一个树,而每条边的价值就是子孙节点重量和乘以单价,可以转换为,此节点重量乘以从根到本节点的最短路,这么一转化,问题瞬间变得简单了。
那么所有点的最短路径一定是一棵树吗? 这个是显然的 ,因为如果形成环了,到达某个点就出现了多个路径,就要删去长的那条,使其没有环
样例中的计算方法
4*40+3*50+2*60+3*(20+40+50+60)+2*30+1*(10+20+30+40+50+60)
=10*1+20*(1+3)+30*(2+1)+40*(4+1+3)+50*(3+1+3)+60*(1+2+3)
=10+80+90+320+350+360
=1210
题目要注意几个地方
1、n=0或者1, 答案是0,而不是no answer
2、数据范围大,要用long long
3、n=0或者1的时候也要将数据读入,不能直接输出0就不管输入了,否则会re
4、注意是无向图,建邻接表的时候要双向
5、数据量大,邻接矩阵不行,必须邻接表
搞清楚了这些,剩下就是简单的spfa了
代码:
#include<stdio.h>#define maxN 50005#define inf 10000000000000struct EDGE {int v,w;int next;}edge[2 * maxN];//邻接表int preEdge[2 * maxN];//preEdge[u],上一条以u为起点的边在edge中的位置long long dis[maxN];//最短路bool vis[maxN];int weight[maxN];//节点重量int queue[20 * maxN];//松弛队列int n,m;void Init()//初始化{for (int i = 1; i <= n; ++ i){preEdge[i] = 0;dis[i] = inf;vis[i] = false;}}void spfa(){int head = 0, tail = 1;queue[0] = 1;dis[1] = 0;while (head < tail){int u = queue[head];vis[u] = true;int p = preEdge[u];//以u为起始点 邻接表中第几条边while (p != 0){int v = edge[p].v, w = edge[p].w;if (dis[v] > dis[u] + w){dis[v] = dis[u] + w;if (!vis[v]){vis[v] = true;queue[tail] = v;tail ++;}}p = edge[p].next;//下一条以u起点的边}head ++;vis[u] = false;}bool flag = true;long long sum = 0;for (int i = 2; i <= n; ++ i){if (dis[i] == inf){flag = false;break;}sum += weight[i] * dis[i];}if (!flag){printf("No Answer\n");}elseprintf("%lld\n", sum);}int main(){int t;scanf("%d", &t);while (t --){scanf("%d%d", &n, &m);for (int i = 1; i <= n; ++ i){scanf("%d", &weight[i]);}Init();int index = 1;for (int i = 1; i <= m; ++ i){int a, b, c;scanf("%d%d%d", &a, &b, &c);edge[index].v = b;edge[index].w = c;edge[index].next = preEdge[a];preEdge[a] = index ++;edge[index].v = a;edge[index].w = c;edge[index].next = preEdge[b];preEdge[b] = index ++;}if (n == 0 || n == 1){printf("0\n");continue;}spfa();}return 0;}
- poj-3013 透过现象看本质,其实都一样
- 透过现象看本质。。。
- 透过现象看本质
- 透过现象看本质(一)
- 透过现象看本质 - 壮志未酬的BPEL
- 大道至简:透过现象看本质
- 透过现象看本质(二)-数据拟合
- 学会透过现象看本质,即使现象有时…
- 淘宝刷钻为何屡禁不止 透过现象看本质
- 程序人生之一 MVC——透过现象看本质
- 透过现象看本质(轻松一下学哲理)
- 透过现象看本质:如何真正实现数据可视化?
- 大道至简之四:透过现象看本质
- 大道至简之五:透过现象看本质
- 大道至简之六:透过现象看本质
- 大道至简之七:透过现象看本质
- 透过现象看本质,解析小米手机成功之道
- 传统金融PK互联网 必须透过现象看本质
- 最新版的havok
- Ubuntu中SVN客户端安装+使用
- C# Split
- 物理加速技术
- rvm的安装, 使用rvm, 安装ruby, 以及gem的使用
- poj-3013 透过现象看本质,其实都一样
- 【100题】二叉树的层序遍历(广度优先遍历)
- HDU/HDOJ----4302 Holedox Eating
- 第10 题 翻转句子中单词的顺序。
- Vision 引擎8.2带来了跨平台的3D游戏技术
- 软件实施工程师
- Ubuntu Android NDK的使用
- 关于强制转换
- boost学习之—Filesystem