哗啦啦村的扩建
2015-08-11 17:26
323 查看
Problem Description
呀呀呀,哗啦啦村在日渐发展中,越来越大了。
唐老师看到这欣欣向荣的情景,感到非常开心。
狗哥在旁边,“喏,我们村子扩建这么快,肯定用了不少钱吧?”
唐老师说:“是呀,不过这些钱都不及我零花钱的万万分之一。”
那么这时候问题来了,唐老师的零花钱至少应该有多少钱呢?
狗哥也想知道这道题的答案,于是他拜托了青君同学,了解到了村子扩建的费用。
啊,原来村子的扩建费用,就是修建道路的费用。
整个村子可以看作有n个房子,村子会修建n-1条道路,保证从任意房子可以到达任意其他房子。
那修建这n-1条道路的费用怎么记呢?对于每条道路,假设这条道路左边有x个房子,右边有y个房子,这条道路长度为k,那么费用就是k*|x-y|。
那么唐老师的零花钱至少有多少钱呢?现在你应该知道了吧。
Input
第一行一个整数,表示这个村子有n个房子
接下来n-1行,表示每条道路的信息,三个整数 a,b,c,表示a,b之间有一条道路,这条路的长度为c
1<=n<=50,000
1≤ai, bi≤n
0 ≤ci≤ 10^6
Output
输出一个整数,表示唐老师的零花钱至少有多少钱
Sample Input
6
1 2 1
1 3 1
1 4 2
6 3 1
5 2 1
Sample Output
2000000000
之前一直不知道链式前向星是什么,这次好好学了- -,但是始终想不通这和动规有什么关系。
链式前向星是要以边为单位来看的,是一个边的集合。
struct Node{
int to;
int next;
int w;
};
其中to就是这条边指向的终点,next就是下一条和这个边同一起点的边,具体操作的时候,是倒着存储的,但是当使用的时候还是要反过来,所以说是下一条边,w就是边的权值,如果有的话。还需要一个head数组来配合。
一开始head数组全为-1或者其他的哨兵值。
void add(int from,int to,int w,int i)
{
node[i].to=to;
node[i].w=w;
node[i].next=head[from];
head[from]=i;
}
from是起点,to是终点,w是权值,i是这条边的序号。前两个就不说了,第三行意思就是这个起点原来的最后一条边的序号,然后更新掉,换为i,那么使用的时候,就是从head[i]找,此时i是起点的序号,就是倒过来,一直到-1停止。
然后这题就是用链式前向星存起来,然后按点来搜,因为这是一棵树,可以保证所有点都搜一次,根据起点来确定边,再以边为单位,计算结果。
还有,最后答案是0就不用输出0000……了,还有,是多组输入……
呀呀呀,哗啦啦村在日渐发展中,越来越大了。
唐老师看到这欣欣向荣的情景,感到非常开心。
狗哥在旁边,“喏,我们村子扩建这么快,肯定用了不少钱吧?”
唐老师说:“是呀,不过这些钱都不及我零花钱的万万分之一。”
那么这时候问题来了,唐老师的零花钱至少应该有多少钱呢?
狗哥也想知道这道题的答案,于是他拜托了青君同学,了解到了村子扩建的费用。
啊,原来村子的扩建费用,就是修建道路的费用。
整个村子可以看作有n个房子,村子会修建n-1条道路,保证从任意房子可以到达任意其他房子。
那修建这n-1条道路的费用怎么记呢?对于每条道路,假设这条道路左边有x个房子,右边有y个房子,这条道路长度为k,那么费用就是k*|x-y|。
那么唐老师的零花钱至少有多少钱呢?现在你应该知道了吧。
Input
第一行一个整数,表示这个村子有n个房子
接下来n-1行,表示每条道路的信息,三个整数 a,b,c,表示a,b之间有一条道路,这条路的长度为c
1<=n<=50,000
1≤ai, bi≤n
0 ≤ci≤ 10^6
Output
输出一个整数,表示唐老师的零花钱至少有多少钱
Sample Input
6
1 2 1
1 3 1
1 4 2
6 3 1
5 2 1
Sample Output
2000000000
之前一直不知道链式前向星是什么,这次好好学了- -,但是始终想不通这和动规有什么关系。
链式前向星是要以边为单位来看的,是一个边的集合。
struct Node{
int to;
int next;
int w;
};
其中to就是这条边指向的终点,next就是下一条和这个边同一起点的边,具体操作的时候,是倒着存储的,但是当使用的时候还是要反过来,所以说是下一条边,w就是边的权值,如果有的话。还需要一个head数组来配合。
一开始head数组全为-1或者其他的哨兵值。
void add(int from,int to,int w,int i)
{
node[i].to=to;
node[i].w=w;
node[i].next=head[from];
head[from]=i;
}
from是起点,to是终点,w是权值,i是这条边的序号。前两个就不说了,第三行意思就是这个起点原来的最后一条边的序号,然后更新掉,换为i,那么使用的时候,就是从head[i]找,此时i是起点的序号,就是倒过来,一直到-1停止。
然后这题就是用链式前向星存起来,然后按点来搜,因为这是一棵树,可以保证所有点都搜一次,根据起点来确定边,再以边为单位,计算结果。
#include<cstdio> #include<cstring> #include<iostream> #include<queue> #include<vector> #include<algorithm> #include<string> using namespace std; long long head[50005], leap[50005], cnt[50005], n; long long ans; struct Node{ long long to; long long next; long long w; }node[100010]; void add(long long from, long long to, long long w, long long i) { node[i].to = to; node[i].w = w; node[i].next = head[from]; head[from] = i; } void dfs(long long x) { leap[x] = 1; long long i; for (i = head[x]; i != -1; i = node[i].next) { long long &temp = node[i].to; if (leap[temp])continue; else { dfs(temp); cnt[x] = cnt[x] + cnt[temp]; ans = ans + node[i].w*(abs(n - 2 * cnt[temp])); } } } int main() { long long i, j, m, t; while (scanf("%lld", &n) != EOF) { memset(head, -1, sizeof(head)); memset(leap, 0, sizeof(leap)); for (i = 1; i <= n; i++) cnt[i] = 1; for (i = 1; i < n; i++) { long long a, b, c; cin >> a >> b >> c; add(a, b, c, i * 2 - 1); add(b, a, c, i * 2); } ans = 0; dfs(1); if (ans == 0) cout << ans << endl; else{ cout << ans; cout << "00000000" << endl; } } return 0; }
还有,最后答案是0就不用输出0000……了,还有,是多组输入……
相关文章推荐
- Android学习笔记
- getchar() putch()的使用
- 26-网络编程-14-网络编程(TCP协议-练习-文本转换服务端)
- fedora21 配置apache共享文件目录
- Chrome不能访问应用商店的解决方法
- 设计模式 策略模式
- 闲来js基础-----2
- Python中xlrd、xlwt、win32com模块对xls文件的读写操作
- hdoj 1102 Constructing Roads 【最小生成树】
- android app记录运行日志 捕获奔溃异常 ,存储日志到文件
- StringBuilder问题
- iScroll上拉刷新下拉加载更多demo,亲自实验过,体验比其它好
- Python小技巧之——基类初始化
- Go-unsafe详解
- N叉树节点绘制
- 26-网络编程-13-网络编程(TCP协议-练习-文本转换客户端)
- 浅谈反射机制
- Linux进程间通信之管道(pipe)、命名管道(FIFO)与信号(Signal)
- POJ1611
- Java基础-ArrayList中ConcurrentModificationException错误解决