Description

在山上一共有N个站点需要检查,检查员从山顶出发去各个站点进行检查,各个站点间有且仅有一条通路,检查员下山前往站点时比较轻松,而上山时却需要额外的时间,问最后检查员检查完所有站点时所需要的额外时间最少是多少。

Input

包含多组数据 每组数据输入第一行为一个整数N 表示站点个数(1<=N<=100000),接下去N-1 行 每行3个整数 x,y,z(1<=z<=10000) 检查站x为检查站y的父节点,x,y之间有一条通路,从y到x需要额外z的时间。(父节点在子节点上方,山顶固定标号为1)

Output

输出一行一个整数表示最少需要花费的额外时间。

Sample Input

6

1 2 1

2 4 1

1 3 1

3 5 1

3 6 1

Sample Output

3

题目乍一看像旅行商问题,但是n这么大,显然不是这么玩的。

考虑到树形结构的特殊性,就是从左子树到右子树,一定要进过父节点才能到达,这点是跟图不一样的。

于是从过程来看,我如果设p[i]表示遍历以i为根的子树所需的最小花费。all[i]表示遍历完并回到i结点的最小花费。当然,起始都是从i结点出发。

那么对于i来说,all[i] = sum(all[k]+dis[k][i])(k是i的子节点)

p[i] = min(sum(all[k]+dis[k][i])+p[j])(其中k != j)

这样的话,用记忆化搜索,便可以得到所有的p和all。p[1]即为所要求。

复杂度是O(n)

但是直接从结果上来看的话,整个遍历的路径,一定是每个线段都一上一下各一次,但是有一条从根部到底部的路径只下不上。(这个从之前的特殊性前提也可以推来)

这样便只需要找这样一条耗费最大的路径,然后用所有路径的和减去它即可。

复杂度也是O(n),但是可以省掉两个数组。

代码:(dp)

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <string>
#include <algorithm>
#define LL long long using namespace std; const int maxN = 1e5+;
int n;
LL all[maxN], p[maxN]; inline LL myMin(LL x, LL y)
{
if (x == -)
return y;
else
return x < y ? x : y;
} //链式前向星
struct Edge
{
int to, next;
int val;
}edge[maxN]; int head[maxN], cnt; void addEdge(int u, int v, int val)
{
edge[cnt].to = v;
edge[cnt].val = val;
edge[cnt].next = head[u];
head[u] = cnt;
cnt++;
} void initEdge()
{
memset(head, -, sizeof(head));
cnt = ;
} void input()
{
initEdge();
memset(all, -, sizeof(all));
memset(p, -, sizeof(p));
int x, y, z;
for (int i = ; i < n; ++i)
{
scanf("%d%d%d", &x, &y, &z);
addEdge(x, y, z);
}
} void dfs(int now)
{
LL s = ;
int to;
for (int k = head[now]; k != -; k = edge[k].next)
{
to = edge[k].to;
if (all[to] == -)
dfs(to);
s += all[to]+edge[k].val;
}
all[now] = s;
for (int k = head[now]; k != -; k = edge[k].next)
{
to = edge[k].to;
p[now] = myMin(p[now], s-all[to]-edge[k].val+p[to]);
}
if (p[now] == -)
p[now] = ;
} void work()
{
dfs();
printf("%I64d\n", p[]);
} int main()
{
//freopen("test.in", "r", stdin);
while (scanf("%d", &n) != EOF)
{
input();
work();
}
return ;
}

ACM学习历程—FZU2195 检查站点(树形DP || 贪心)的更多相关文章

  1. ACM学习历程—HDU 1059 Dividing(dp && 多重背包)

    Description Marsha and Bill own a collection of marbles. They want to split the collection among the ...

  2. ACM学习历程—ZOJ3471 Most Powerful(dp && 状态压缩 && 记忆化搜索 && 位运算)

    Description Recently, researchers on Mars have discovered N powerful atoms. All of them are differen ...

  3. ACM学习历程—HDU1003 Max Sum(dp && 最大子序列和)

    Description Given a sequence a[1],a[2],a[3]......a[n], your job is to calculate the max sum of a sub ...

  4. ACM学习历程—HDU4415 Assassin’s Creed(贪心)

    Problem Description Ezio Auditore is a great master as an assassin. Now he has prowled in the enemie ...

  5. ACM学习历程——HDU 5014 Number Sequence (贪心)(2014西安网赛)

    Description There is a special number sequence which has n+1 integers. For each number in sequence, ...

  6. ACM学习历程——POJ 1700 Crossing River(贪心)

    Description A group of N people wishes to go across a river with only one boat, which can at most ca ...

  7. ACM学习历程——POJ 2376 Cleaning Shifts(贪心)

    Description Farmer John is assigning some of his N (1 <= N <= 25,000) cows to do some cleaning ...

  8. 【bzoj4027】[HEOI2015]兔子与樱花 树形dp+贪心

    题目描述 很久很久之前,森林里住着一群兔子.有一天,兔子们突然决定要去看樱花.兔子们所在森林里的樱花树很特殊.樱花树由n个树枝分叉点组成,编号从0到n-1,这n个分叉点由n-1个树枝连接,我们可以把它 ...

  9. [BZOJ1596] [Usaco2008 Jan]电话网络(树形DP || 贪心)

    传送门 1.树形DP #include <cstdio> #include <cstring> #include <iostream> #define N 1000 ...

随机推荐

  1. iOS开发 剖析网易新闻标签栏视图切换(addChildViewController属性介绍)

    本文转载至 http://www.tuicool.com/articles/3ymMzub CSDN博客原文  http://blog.csdn.net/hmt20130412/article/det ...

  2. fiddler 清除证书+重新添加证书

    1. 清除证书 ①任意浏览器,打开Internet属性弹窗,点击内容页签下<证书> ②删除个人页签下,颁发者为DO_NOT_TRUST_Fiddler**的数据 2. 重新认证证书 ①打开 ...

  3. 九度OJ 1195:最长&最短文本 (搜索)

    时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:3144 解决:1156 题目描述: 输入多行字符串,请按照原文本中的顺序输出其中最短和最长的字符串,如果最短和最长的字符串不止一个,请全部输 ...

  4. php在web端播放amr语音(如微信语音)

    在使用微信JSSDK的上传下载语音接口时,发现一个问题: 下载的语音在iPhone上不能播放,测试了之后原因竟然是: 微信接口返回的音频内容是amr格式的,但iPhone不支持播放此类型格式. 那么转 ...

  5. SocketAsyncEventArgs里的AcceptSocket能独立存在吗?

    独立存在是什么意思? 先来看一个例子.我们知道一个Socket对象(我们叫他ListenScoket)可以调用AcceptAsync并接受一个SocketAsyncEventArgs对象,如果操作成功 ...

  6. Swift来了,是不是能够入手IOS开发了?

    在今天的WWDC2014上,苹果公布了一种全新的Swift.在苹果高管 Craig Federighi 的描写叙述中,Swift 在各个方面优于 Objective-C,也不会有那么多复杂的符号和表达 ...

  7. python+NLTK 自然语言学习处理七:N-gram标注

    在上一章中介绍了用pos_tag进行词性标注.这一章将要介绍专门的标注器. 首先来看一元标注器,一元标注器利用一种简单的统计算法,对每个标识符分配最有可能的标记,建立一元标注器的技术称为训练. fro ...

  8. tool class

    在Java中,工具类定义了一组公共方法,这篇文章将介绍Java中使用最频繁及最通用的Java工具类.以下工具类.方法按使用流行度排名,参考数据来源于Github上随机选取的5万个开源项目源码. 一. ...

  9. Python 面试题(下)

    接上篇. 网络 1 三次握手 客户端通过向服务器端发送一个SYN来创建一个主动打开,作为三路握手的一部分.客户端把这段连接的序号设定为随机数 A. 服务器端应当为一个合法的SYN回送一个SYN/ACK ...

  10. QMessageBox简单使用

    首先要调用 #include <QMessageBox> 然后 QMessageBox msgBox; msgBox.setWindowTitle("错误"); msg ...