hdu3586 Information Disturbing[二分答案+树形DP]

给定 n 个节点的树,边有权值。1 号点是根,除了 1 号点外的度数为 1 的节点是叶子。
要求切断所有叶子和 1 号点之间的联系,切断一条边要花费这条边上权值对应的代价,要求总的代价不超过 m。
在满足这个前提下要求切断的边权的最大值最小,求出这个最小值。$n ≤ 10^5$



首先这个最大值肯定二分答案,然后树形DP限制割掉的边不能超过这个二分的边权,设$f[i]$表示在这个限制下该子树内所有叶子断绝与根的联系的最小代价。

于是$f[i]=max(w_{father},\sum\limits_{y}f[y])$。也就是要不然割自己与父亲的边,要不然让所有儿子和自己都断掉。不合法的方案用INF来传递。

然后判一下是否$f[1]\le m$即可。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<cmath>
 6 #define dbg(x) cerr << #x << " = " << x <<endl
 7 using namespace std;
 8 typedef long long ll;
 9 typedef double db;
10 typedef pair<int,int> pii;
11 template<typename T>inline T _min(T A,T B){return A<B?A:B;}
12 template<typename T>inline T _max(T A,T B){return A>B?A:B;}
13 template<typename T>inline char MIN(T&A,T B){return A>B?(A=B,1):0;}
14 template<typename T>inline char MAX(T&A,T B){return A<B?(A=B,1):0;}
15 template<typename T>inline void _swap(T&A,T&B){A^=B^=A^=B;}
16 template<typename T>inline T read(T&x){
17     x=0;int f=0;char c;while(!isdigit(c=getchar()))if(c==‘-‘)f=1;
18     while(isdigit(c))x=x*10+(c&15),c=getchar();return f?x=-x:x;
19 }
20 const int N=1e5+7,INF=0x1f1f1f1f;
21 int n,mid,L,R,m;
22 struct STOthxORZ{int to,nxt,w;}G[N<<1];
23 int Head[N],tot;
24 inline void Addedge(int x,int y,int z){
25     G[++tot].to=y,G[tot].nxt=Head[x],Head[x]=tot,G[tot].w=z;
26     G[++tot].to=x,G[tot].nxt=Head[y],Head[y]=tot,G[tot].w=z;
27 }
28 int f[N];
29 #define y G[j].to
30 inline void dp(int x,int fa,int val){
31     int ret=0;
32     for(register int j=Head[x];j;j=G[j].nxt)if(y^fa)dp(y,x,G[j].w),ret+=f[y],(ret>=INF)&&(ret=INF);
33     f[x]=_min((val>mid?INF:val),(ret?ret:INF));
34 }
35 #undef y
36 int main(){//freopen("test.in","r",stdin);//freopen("test.ans","w",stdout);
37     while(read(n),read(m),n||m){
38         memset(Head,0,sizeof Head);tot=0;L=1;R=0;
39         for(register int i=1,x,y,z;i<n;++i)read(x),read(y),read(z),Addedge(x,y,z),MAX(R,z);
40         int tmp=++R;
41         while(L<R){
42             memset(f,0x1f,sizeof f);
43             mid=L+R>>1;dp(1,0,INF);
44             if(f[1]<=m)R=mid;
45             else L=mid+1;
46         }
47         printf("%d\n",L==tmp?-1:L);
48     }
49     return 0;
50 }

原文地址:https://www.cnblogs.com/saigyouji-yuyuko/p/11511070.html

时间: 2024-10-12 19:43:45

hdu3586 Information Disturbing[二分答案+树形DP]的相关文章

BZOJ 2097 Exercise 奶牛健美操 二分答案+树形DP+贪心

题目大意:给定一棵树,可以删掉k条边,求删掉后森林中所有树直径的最大值的最小值 最大值最小,典型的二分答案 此题我们二分树的直径,每次二分DFS一次,对于每个节点统计出所有子树删边后的dis,排序,贪心删掉最大的,直到最大的两个子树相加不会超过二分的答案为止 时间复杂度O(nlog^2n) 老子的二分居然写挂了...桑不起啊啊啊啊 #include<cstdio> #include<cstring> #include<iostream> #include<algo

[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

[HDU3586]Information Disturbing(DP + 二分)

传送门 二分答案,再 DP,看看最终结果是否小于 m ——代码 1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #define N 1001 5 #define max(x, y) ((x) > (y) ? (x) : (y)) 6 7 int n, m, cnt, ans; 8 int a[N], sum[N], head[N], to[N << 1], val[N &

POJ 3208 Apocalypse Someday 二分答案+数位DP

这题应该是POJ最强大的一道数位DP了吧 正解是AC自动机 不会 还是写数位DP吧 题目大意:我们令含有666的数字为不吉利数字,则可以得到一个递增数列: {an}=666,1666,2666,3666,4666,5666,6660,6661,.... 给定n,求an 首先我们把这个问题转化成另一个问题:给定n,求1~n中有多少个数含有666 解决了这个问题,把原问题二分答案即可 首先预处理f数组,令 f[i][0]表示i位数中首位不为6且不含666的数的数量 f[i][1]表示i位数中首位连续

BZOJ 2525 Poi2011 Dynamite 二分答案+树形贪心

题目大意:给定一棵树,有一些点是关键点,要求选择不超过m个点,使得所有关键点到最近的选择的点距离最大值最小 二分答案,问题转化为: 给定一棵树,有一些点是关键点,要求选择最少的点使得每个关键点到选择的点的距离不超过limit 然后我们贪心DFS一遍 对于以一个节点为根的子树,有三种状态: 0.这棵子树中存在一个选择的点,这个选择的点的贡献还能继续向上传递 1.这棵子树中存在一个未被覆盖的关键点,需要一些选择的点去覆盖他 2.这棵子树中既没有能继续向上传递的选择的点也不存在未覆盖的关键点 是不是少

HDU-3586 Information Disturbing(树形DP+删边)

题目大意:一棵有n个节点的有根树,1为根节点,边带权,表示删掉这条边的代价.现在要删掉一些边,使叶子节点不能到达根节点.但是,每次删除的边的代价不能超过limit,删掉的边的总代价不能超过m,求最小的limit的可能取值. 题目分析:二分枚举limit,定义状态dp(u)表示将u与它管辖的叶子节点失去联系所需要的总代价,则: dp(u)+=min(dp(son),e[i].w),e[i].w<=limit: dp(u)+=dp(son)  e[i].w>limit: 代码如下: # inclu

HDU 3586 Information Disturbing (二分+树形dp)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3586 给定n个敌方据点,1为司令部,其他点各有一条边相连构成一棵树,每条边都有一个权值cost表示破坏这条边的费用,叶子节点为前线.现要切断前线和司令部的联系,每次切断边的费用不能超过上限limit,问切断所有前线与司令部联系所花费的总费用少于m时的最小limit.1<=n<=1000,1<=m<=10^6 dp[i]表示i节点为root的这个子树所破坏的最少费用,if(cost[i]

【CF739B】Alyona and a tree(树上差分,二分,树形DP)

题意:给出一棵有根树,树上每个点.每条边都有一个权值. 现在给出"控制"的定义:对一个点u,设点v在其子树上,且dis(u,v)≤av,则称u控制v. 要求求出每个点控制了多少个点 n (1?≤?n?≤?2·105).  (1?≤?ai?≤?109) 1?≤?pi?≤?n, 1?≤?wi?≤?109) 思路:在学校CF有时上不去不知道为什么 对于确定的点i,计算它对哪些点有贡献 dis[i]-dis[u]<=a[i] dis[u]<=a[i]-dis[i]满足二分性 倍增枚

【转】【DP_树形DP专辑】【9月9最新更新】【from zeroclock&#39;s blog】

树,一种十分优美的数据结构,因为它本身就具有的递归性,所以它和子树见能相互传递很多信息,还因为它作为被限制的图在上面可进行的操作更多,所以各种用于不同地方的树都出现了,二叉树.三叉树.静态搜索树.AVL树,线段树.SPLAY树,后缀树等等.. 枚举那么多种数据结构只是想说树方面的内容相当多,本专辑只针对在树上的动态规划,即树形DP.做树形DP一般步骤是先将树转换为有根树,然后在树上进行深搜操作,从子节点或子树中返回信息层层往上更新至根节点.这里面的关键就是返回的信息部分,这个也没一般性的东西可讲