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 }
View Code

猜你喜欢

转载自www.cnblogs.com/saigyouji-yuyuko/p/11511070.html