3743: [Coci2015]Kamp
来源:互联网 发布:structure软件 使用 编辑:程序博客网 时间:2024/04/30 14:37
3743: [Coci2015]Kamp
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 442 Solved: 210
[Submit][Status][Discuss]
Description
一颗树n个点,n-1条边,经过每条边都要花费一定的时间,任意两个点都是联通的。
有K个人(分布在K个不同的点)要集中到一个点举行聚会。
聚会结束后需要一辆车从举行聚会的这点出发,把这K个人分别送回去。
请你回答,对于i=1~n,如果在第i个点举行聚会,司机最少需要多少时间把K个人都送回家。
Input
第一行两个数,n,K。
接下来n-1行,每行三个数,x,y,z表示x到y之间有一条需要花费z时间的边。
接下来K行,每行一个数,表示K个人的分布。
Output
输出n个数,第i行的数表示:如果在第i个点举行聚会,司机需要的最少时间。
Sample Input
7 2
1 2 4
1 3 1
2 5 1
2 4 2
4 7 3
4 6 2
3
7
1 2 4
1 3 1
2 5 1
2 4 2
4 7 3
4 6 2
3
7
Sample Output
11
15
10
13
16
15
10
15
10
13
16
15
10
HINT
【数据规模】
K <= N <= 500000
1 <= x,y <= N, 1 <= z <= 1000000
Source
随意选择一个起点,以它为根,司机的载人过程可以这样考虑
每次选择一个有关键点的子树,往那里走,把所有在里面的人送到家以后再回来
这样最后会回到根,每条需要经过的边恰好经过两次
不过并没有规定最后要回来,所以选择一条最长的路径,这条路径上的边只经过一次就行了
用树形dp维护一下,然后维护链长的最大值和次大值,方便换根的时候转移
#include<iostream>#include<cstdio>#include<algorithm>#include<cmath>#include<cstring>#include<vector>#include<queue>#include<set>#include<map>#include<stack>#include<bitset>#include<ext/pb_ds/priority_queue.hpp>using namespace std; const int maxn = 5E5 + 50;typedef long long LL;const LL INF = 1E16; struct E{ int to; LL w; E(){} E(int to,LL w): to(to),w(w){}}; int n,k;LL f[maxn],g[maxn],h[maxn],fr[maxn],sc[maxn],pos[maxn],siz[maxn]; vector <E> v[maxn]; void Dfs1(int x,int fa){ fr[x] = sc[x] = -INF; if (siz[x] == 1) fr[x] = 0,pos[x] = -1; for (int i = 0; i < v[x].size(); i++) { E e = v[x][i]; if (e.to == fa) continue; Dfs1(e.to,x); f[x] += f[e.to]; siz[x] += siz[e.to]; if (siz[e.to]) { f[x] += 2LL * e.w; LL Fr = fr[e.to] != -INF ? e.w + fr[e.to] : -INF; LL Sc = sc[e.to] != -INF ? e.w + sc[e.to] : -INF; if (Fr <= fr[x]) sc[x] = max(sc[x],Fr); else pos[x] = i,sc[x] = fr[x],fr[x] = Fr; } }} void Dfs2(int x,int fa,LL sum,int tot,LL Max){ h[x] = max(fr[x],Max); g[x] = sum + f[x]; for (int i = 0; i < v[x].size(); i++) { E e = v[x][i]; if (e.to == fa) continue; LL Nex,ma = -INF; int cnt; if (Max != -INF) ma = Max + e.w; if (pos[x] != i && fr[x] != -INF) ma = max(ma,fr[x] + e.w); else if (sc[x] != -INF) ma = max(ma,sc[x] + e.w); cnt = tot + siz[x] - siz[e.to]; Nex = sum + f[x] - f[e.to]; if (cnt && !siz[e.to]) Nex += 2LL * e.w; else if (!cnt && siz[e.to]) Nex -= 2LL * e.w; Dfs2(e.to,x,Nex,cnt,ma); }} int getint(){ char ch = getchar(); int ret = 0; while (ch < '0' || '9' < ch) ch = getchar(); while ('0' <= ch && ch <= '9') ret = ret * 10 + ch - '0',ch = getchar(); return ret;} char s[20];void Print(LL x){ if (!x) {puts("0"); return;} int len = 0; while (x) s[++len] = x % 10,x /= 10; for (int i = len; i; i--) putchar(s[i] + '0'); puts("");} int main(){ #ifdef DMC freopen("DMC.txt","r",stdin); #endif n = getint(); k = getint(); if (!k) { for (int i = 1; i <= n; i++) puts("0"); return 0; } for (int i = 1; i < n; i++) { int x = getint(),y,w; y = getint(); w = getint(); v[x].push_back(E(y,w)); v[y].push_back(E(x,w)); } for (int i = 1; i <= k; i++) siz[getint()] = 1; Dfs1(1,0); Dfs2(1,0,0,0,-INF); for (int i = 1; i <= n; i++) Print(g[i] - h[i]); return 0;}
0 0
- 3743: [Coci2015]Kamp BFS
- 3743: [Coci2015]Kamp
- BZOJ 3743: [Coci2015]Kamp 树形dp
- [bzoj3743][Coci2015]Kamp
- [COCI 2015] kamp 聚会
- bzoj3743 Kamp bfs
- 2017.9.17 kamp 思考记录
- [Coci2015]Stanovi解题报告
- bzoj3745: [Coci2015]Norma
- 【COCI2015】【BZOJ3810】Stanovi
- BZOJ Coci2015 Divljak
- bzoj 3810: [Coci2015]Stanovi
- BZOJ 3881 [Coci2015]Divljak
- BZOJ P3810[Coci2015]Stanovi
- BZOJ3810 [Coci2015]Stanovi
- 3810: [Coci2015]Stanovi
- 【COCI2015】bzoj3881 Divljak
- Coci2015泛做
- 模拟掷骰子
- 面试的角度诠释Java工程师(一)
- 8VC Venture Cup 2017
- webservice
- 图-有权图-最短路径算法
- 3743: [Coci2015]Kamp
- iOS
- PAT B1044/A1100 Mars Numbers (20)
- MySQL数据库基础(一)(启动-停止、登录-退出、语法规范及最基础操作)(持续更新中)
- 抽象类详解
- JavaScript创建对象的方式
- 使用Git分布式版本控制系统
- 最通俗易懂的网络应用层协议详解
- 10 种机器学习算法的要点(附 Python 和 R 代码)(转载)