HDU 5886 Tower Defence(2016青岛网络赛 I题,树的直径 + DP)

题目链接  2016 Qingdao Online Problem I

题意  在一棵给定的树上删掉一条边,求剩下两棵树的树的直径中较长那的那个长度的期望,答案乘上$n-1$后输出。

先把原来那棵树的直径求出来。显然删掉的边不是这条直径上的边,那么这时答案就是这条直径的长度。

否则就是直径的某个端点到某一个点(要求连通)的距离的最大值。

在整条链上做两次$DP$之后枚举取较大值即可。

#include <bits/stdc++.h>

using namespace std;

#define rep(i, a, b)	for (int i(a); i <= (b); ++i)
#define dec(i, a, b)	for (int i(a); i >= (b); --i)
#define fi		first
#define se		second

typedef long long LL;

const int N = 100010;

vector <pair<int, LL > > v[N];
int T, n, L, R, x, cnt;
int a[N], f[N], father[N];
LL b[N], c[N], s[N], cl[N], cr[N], c1, c2, num, ans = 0;

void dfs1(int x, int fa, LL now){
	if (now > c1){
		c1 = now;
		L = x;
	}

	for (auto node : v[x]){
		int u = node.fi;
		LL w = node.se;
		if (u == fa) continue;
		dfs1(u, x, now + w);
	}
}

void dfs2(int x, int fa, LL now){
	father[x] = fa;
	s[x] = now;
	if (now > c2){
		c2 = now;
		R = x;
	}

	for (auto node : v[x]){
		int u = node.fi;
		LL w = node.se;
		if (u == fa) continue;
		dfs2(u, x, now + w);
	}
}

void dfs3(int w, int x, LL now){
	f[x] = 1;
	c[w] = max(c[w], now);
	for (auto node : v[x]){
		int u = node.fi;
		if (f[u]) continue;
		dfs3(w, u, now + node.se);
	}
}

int main(){

	for (scanf("%d", &T); T--; ){
		scanf("%d", &n);
		rep(i, 0, n + 1) v[i].clear();
		rep(i, 2, n){
			int x, y;
			LL z;
			scanf("%d%d%lld", &x, &y, &z);
			v[x].push_back({y, z});
			v[y].push_back({x, z});
		}

		L = -1; c1 = -1;
		dfs1(1, 0, 0);
		R = -1, c2 = -1;
		memset(father, 0, sizeof father);
		dfs2(L, 0, 0);

		x = R;
		cnt = 0;
		while (true){
			a[++cnt] = R;
			R = father[R];
			if (R == 0) break;
		}

		rep(i, 1, cnt) b[i] = s[a[i]];
		reverse(a + 1, a + cnt + 1);
		reverse(b + 1, b + cnt + 1);

		num = b[cnt];
		ans = num * (n - cnt);

		memset(f, 0, sizeof f);
		rep(i, 1, cnt) f[a[i]] = 1;

		rep(i, 1, cnt){
			c[i] = 0;
			dfs3(i, a[i], 0);
		}

		cl[1] = b[1]; rep(i, 2, cnt) cl[i] = max(cl[i - 1], b[i] + c[i]);
		cr[cnt] = 0;  dec(i, cnt - 1, 1) cr[i] = max(cr[i + 1], b[cnt] - b[i] + c[i]);
		rep(i, 1, cnt - 1) ans = ans + max(cl[i], cr[i + 1]);
		printf("%lld\n", ans);
	}

	return 0;
}

原文地址:https://www.cnblogs.com/cxhscst2/p/8467836.html

时间: 2024-10-14 08:38:12

HDU 5886 Tower Defence(2016青岛网络赛 I题,树的直径 + DP)的相关文章

HDU 5880 Family View (2016 青岛网络赛 C题,AC自动机)

题目链接  2016 青岛网络赛  Problem C 题意  给出一些敏感词,和一篇文章.现在要屏蔽这篇文章中所有出现过的敏感词,屏蔽掉的用$'*'$表示. 建立$AC$自动机,查询的时候沿着$fail$指针往下走,当匹配成功的时候更新$f[i]$ $f[i]$表示要屏蔽以第$i$个字母结尾的长度为$f[i]$的字符串. 原文地址:https://www.cnblogs.com/cxhscst2/p/8452147.html

hdu 5901 Count primes (2016沈阳网络赛)

原题地址:http://acm.hdu.edu.cn/showproblem.php?pid=5901 题意:输入n,输出n以内质数个数 模板题,模板我看不懂,只是存代码用. 官方题解链接:https://async.icpc-camp.org/d/560-2016 /************************************************************ 这个模板我一点都不会,代码是从codeforces上抄的,佚名 pi(i)表示i以内质数的个数 ******

2016青岛网络赛滚粗记

TonyFang+Sps+我=5/12 滚了个大粗   01 I count two three 题意:求形同的数中大于n的最小值 题解:预处理所有的(5194个),在这里面二分 #include<map> #include<stack> #include<queue> #include<cstdio> #include<string> #include<vector> #include<cstring> #include

2016青岛网络赛 The Best Path

The Best Path Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others) Problem Description Alice is planning her travel route in a beautiful valley. In this valley, there are N lakes, and M rivers linking these lakes. Alice

HDU 5014 Number Sequence(西安网络赛H题)

HDU 5014 Number Sequence 题目链接 思路:对于0-n,尽量不让二进制中的1互相消掉就是最优的,那么只要两个数只要互补就可以了,这样每次从最大的数字,可以找到和他互补的数字,然后这个区间就能确定了,然后剩下的递归下去为一个子问题去解决 代码: #include <cstdio> #include <cstring> const int N = 100005; int n, a[N], ans[N]; int cnt[N]; int count(int x) {

HDU 5015 233 Matrix(西安网络赛I题)

HDU 5015 233 Matrix 题目链接 思路:矩阵快速幂,观察没一列,第一个和为左边加最上面,第二个可以拆为左边2个加最上面,第三个可以拆为为左边3个加最上面,这样其实只要把每一列和每一列右边那列的233构造出一个矩阵,进行矩阵快速幂即可 代码: #include <cstdio> #include <cstring> typedef long long ll; const int N = 15; const int MOD = 10000007; int n, m; s

HDU 5009 Paint Pearls(西安网络赛C题)

HDU 5009 Paint Pearls 题目链接 题意:给定一个目标颜色,每次能选一个区间染色,染色的代价为这个区间不同颜色数的平方,问最小代价 思路:先预处理,把相同颜色的一段合并成一个点,然后把颜色离散化掉,然后进行dp,dp[i]表示染到第i个位置的代价,然后往后转移,转移的过程记录下不同个数,这样就可以转移了,注意加个剪枝,就是如果答案大于了dp[n]就不用往后继续转移了 代码: #include <cstdio> #include <cstring> #include

HDU 5009 Paint Pearls(西安网络赛C题) dp+离散化+优化

转自:http://blog.csdn.net/accelerator_/article/details/39271751 吐血ac... 11668627 2014-09-16 22:15:24 Accepted 5009 1265MS 1980K 2290 B G++ czy   Paint Pearls Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Subm

ACM-ICPC 2018青岛网络赛-H题

把这题的每个点分成两种情况看,如果是从这个点开始,0算作2,1算作1,如果是中间点或者是结束点,如果和前面的相同看作2,不相同看作1 #include <iostream> #include <string> #include <string.h> using namespace std; int main() { ios::sync_with_stdio(false); int t; cin >> t; while (t--) { int a, b; st