http://acm.split.hdu.edu.cn/showproblem.php?pid=3586
题意 : 给定一个带权无向树,要切断所有叶子节点和1号节点(总根)的联系,每次切断边的费用不能超过上限limit,问在保证总费用<=m下的最小的limit。
显然最小的总费用和最小的limit不能同时维护,那么只能在dfs中维护一个然后另一个用特殊的(朗诵)技巧解决……
emmmmmmmmm……说白了就是二分求最小的limit,然后就没有下面了。
算是普通难度,只要知道二分就很好写,虽然我开始没有想到(捂脸),还是意识不够。
下面是代码 细长的代码非常丑所以删了一些换行,如果操作失误删掉一些奇怪东西导致不能AC,劳烦看官老爷自己再改改
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 #include<cmath> 6 using namespace std; 7 const int maxn=1010; 8 int maxx=0; 9 int t,n,m; 10 int f[maxn]={};//子代lim值 11 int he[maxn]={};//对应的和 12 int vis[maxn]={}; 13 struct nod{ 14 int y; 15 int next; 16 int v; 17 }e[2*maxn]={}; 18 int head[maxn]={},tot; 19 void init(int x,int y,int v){ 20 e[++tot].y=y; 21 e[tot].v=v; 22 e[tot].next=head[x]; 23 head[x]=tot; 24 } 25 bool dfs(int x,int ls,int sum){ 26 int y,v; 27 vis[x]=1; 28 for(int i=head[x];i;i=e[i].next){ 29 y=e[i].y; v=e[i].v; 30 if((!vis[y])){ 31 if(dfs(y,ls,sum-he[x])){ 32 if(f[y]!=0){ 33 if(v<=ls&&v<he[y]){ 34 f[x]=max(f[x],v); he[x]+=v; 35 }else{ 36 f[x]=max(f[x],f[y]); he[x]+=he[y]; 37 } 38 }else{ 39 if(v<=ls){ 40 f[x]=max(f[x],v); he[x]+=v; 41 }else{ 42 if(x==1){ return 0; } 43 f[x]=0; return 1; 44 } 45 }if(he[x]>sum){ 46 if(x==1){ return 0; } 47 f[x]=0; return 1; 48 } 49 }else{ return 0; } 50 } 51 } 52 return 1; 53 } 54 void yu(){ 55 tot=0; maxx=0; 56 memset(f,0,sizeof(f)); 57 memset(he,0,sizeof(he)); 58 memset(vis,0,sizeof(vis)); 59 memset(head,0,sizeof(head)); 60 } 61 void yu2(){ 62 memset(vis,0,sizeof(vis)); 63 memset(f,0,sizeof(f)); 64 memset(he,0,sizeof(he)); 65 } 66 int doit(){ 67 int l=1,r=maxx; 68 while(r-l>1){ 69 int md=(l+r)/2; yu2(); 70 if(dfs(1,md,m)){ r=md; } 71 else{ l=md; } 72 }yu2(); 73 if(dfs(1,l,m)){ return l; } 74 yu2(); 75 if(dfs(1,r,m)){ return r; } 76 return -1; 77 } 78 int main(){ 79 for(;1;){ 80 yu(); 81 scanf("%d%d",&n,&m); 82 if(n==0&&m==0){ break; } 83 int x,y,v; 84 for(int i=1;i<n;i++){ 85 scanf("%d%d%d",&x,&y,&v); 86 maxx=max(maxx,v); 87 init(x,y,v); 88 init(y,x,v); 89 } 90 cout<<doit()<<endl; 91 } 92 return 0; 93 }