[bzoj3420]Poi2013 Triumphal arch_树形dp_二分

Triumphal arch

题目链接https://lydsy.com/JudgeOnline/problem.php?id=3420

数据范围:略。



题解

首先,发现$ k $具有单调性,我们可以二分。

现在考虑怎么验证?

看了题解...

我们设$ f_i $表示,如果当前人在$i$且要求合法的情况下,$i$的子树中最多要预先处理好多少个节点。

然后暴力树形$dp$转移即可。

代码

#include <bits/stdc++.h>

#define N 1000010 

using namespace std;

char *p1, *p2, buf[100000];

#define nc() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 100000, stdin), p1 == p2) ? EOF : *p1 ++ )

int rd() {
	int x = 0, f = 1;
	char c = nc();
	while (c < 48) {
		if (c == ‘-‘)
			f = -1;
		c = nc();
	}
	while (c > 47) {
		x = (((x << 2) + x) << 1) + (c ^ 48), c = nc();
	}
	return x * f;
}

int head[N], to[N << 1], nxt[N << 1], tot;

inline void add(int x, int y) {
	to[ ++ tot] = y;
	nxt[tot] = head[x];
	head[x] = tot;
}

int sz[N], ssz[N];

void dfs1(int p, int fa) {
	sz[p] = 1;
	for (int i = head[p]; i; i = nxt[i]) {
		if (to[i] != fa) {
			ssz[p] ++ ;
			dfs1(to[i], p);
			sz[p] += sz[to[i]];
		}
	}
}
int k, f[N];

void dfs(int p, int fa) {
	f[p] = -k;
	for (int i = head[p]; i; i = nxt[i]) {
		if (to[i] != fa) {
			dfs(to[i], p);
			f[p] += f[to[i]] + 1;
		}
	}
	f[p] = max(f[p], 0);
}

bool check(int x) {
	k = x;
	dfs(1, 1);
	if (f[1]) {
		return false;
	}
	else {
		return true;
	}
}

int main() {
	int n = rd();
	for (int i = 1; i < n; i ++ ) {
		int x = rd(), y = rd();
		add(x, y), add(y, x);
	}
	dfs1(1, 1);
	if (n == 1) {
		puts("0");
		return 0;
	}
	int l = 1, r = n, ans = n;
	while (l <= r) {
		int mid = (l + r) >> 1;
		// cout << mid << endl ;
		if (check(mid)) {
			r = mid - 1;
			ans = mid;
		}
		else {
			l = mid + 1;
		}
	}
	cout << ans << endl ;
	return 0;
}

原文地址:https://www.cnblogs.com/ShuraK/p/11773512.html

时间: 2024-10-07 23:13:36

[bzoj3420]Poi2013 Triumphal arch_树形dp_二分的相关文章

[bzoj2097][Usaco2010 Dec]Exercise 奶牛健美操_贪心_树形dp_二分

Exercise bzoj-2097 Usaco-2010 Dec 题目大意:题目链接 注释:略. 想法:题目描述生怕你不知道这题在考二分. 关键是怎么验证?我们想到贪心的删边. 这样的策略是显然正确的. 之后树形dp的时候维护一下就行. 最后,附上丑陋的代码... ... #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #define N 10001

hdu3586 树形dp+二分求解

http://acm.hdu.edu.cn/showproblem.php?pid=3586 Problem Description In the battlefield , an effective way to defeat enemies is to break their communication system. The information department told you that there are n enemy soldiers and their network w

hdu 3586 树形dp+二分

题目大意:给定n个敌方据点,1为司令部,其他点各有一条边相连构成一棵 树,每条边都有一个权值cost表示破坏这条边的费用,叶子节点为前线.现要切断前线和司令部的联系,每次切断边的费用不能超过上限limit,问切断所 有前线与司令部联系所花费的总费用少于m时的最小limit.1<=n<=1000,1<=m<=100万 题目要问的是最小的最大限制,必然二分答案 然后对于每一个值,树形DP判定是否可行 dp[i]表示要切断以i为根的其它所有子树的最小代价. 其中设定叶子结点的代价为无穷大

[hdu3586]Information Disturbing树形dp+二分

题意:给出一棵带权无向树,以及给定节点1,总约束为$m$,找出切断与所有叶子节点联系每条边所需要的最小价值约束. 解题关键:二分答案,转化为判定性问题,然后用树形dp验证答案即可. dp数组需要开到ll,如果用设inf的解法. 1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int maxn=1e6+7; 5 const int inf=0x3f3f3f3f; 6 struct e

UvaLive 6534 Join two kingdoms 树形DP+二分

链接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4545 题意:两个国家A,B,分别有N座城市和Q座城市(1 ≤ N, Q ≤ 4 × 10^4),每个国家里的城市都是树形结构,每条边的权值都是1.现在要随机从两个国家中各选择一个城市来将两个国家连接起来,问连接起来的大国家里面的最长路的期望是多少. 思路:首先用树形DP

[coci2015-2016 coii] torrent【树形dp 二分】

传送门:http://www.hsin.hr/coci/archive/2015_2016/ 进去之后点最下面那个. 这道题没有想出来,可惜了,其实不难的. 题目是两个"源"的,我们先考虑单源的问题.先把这个源拉成树根,然后设f(i)为以结点i为树根的子树,全部收到文件所需要的时间,由于同一时间,结点i只能向其中一个子结点传送文件,那么假设son(i, j)表示结点i的第j个子结点(程序中不需要这个数组,这里只是为了叙述方便),那么f(i) = max{ j + f( son(i, j

HDU 3586 Information Disturbing 树形DP+二分

Information Disturbing Problem Description In the battlefield , an effective way to defeat enemies is to break their communication system.The information department told you that there are n enemy soldiers and their network which have n-1 communicati

HDU3585 Information Disturbing 树形dp+二分

http://acm.split.hdu.edu.cn/showproblem.php?pid=3586 题意 : 给定一个带权无向树,要切断所有叶子节点和1号节点(总根)的联系,每次切断边的费用不能超过上限limit,问在保证总费用<=m下的最小的limit. 显然最小的总费用和最小的limit不能同时维护,那么只能在dfs中维护一个然后另一个用特殊的(朗诵)技巧解决-- emmmmmmmmm--说白了就是二分求最小的limit,然后就没有下面了. 算是普通难度,只要知道二分就很好写,虽然我开

[poj3107]Godfather_树形dp_树的重心

Godfather poj-3107 题目大意:求树的重心裸题. 注释:n<=50000. 想法:我们尝试用树形dp求树的重心,关于树的重心的定义在题目中给的很明确.关于这道题,我们邻接矩阵存不下,用链式前向星存边,然后对于任选节点遍历,然后在回溯是进行最大值的最小值更新,之后就是一点显然的结论——树最多只有两个重心,而且这两个加点必须连边. 最后,附上丑陋的代码... ... #include <iostream> #include <cstdio> #include &l