题意:https://ac.nowcoder.com/acm/contest/4370
将一棵树切k-1刀分成k棵树,问这k棵树里最大的权值的最小值是多少
思路:https://www.cnblogs.com/ucprer/p/11931263.html
二分最大值。
dfs割子树,每次从下往上切一个最大的树。
单个dfs表示保证当前节点可切,然后子树dfs完了,sort子树,选最大的切,直到当前u节点也可切
1 #define IOS ios_base::sync_with_stdio(0); cin.tie(0); 2 #include <cstdio>//sprintf islower isupper 3 #include <cstdlib>//malloc exit strcat itoa system("cls") 4 #include <iostream>//pair 5 #include <fstream>//freopen("C:\Users\13606\Desktop\Input.txt","r",stdin); 6 #include <bitset> 7 //#include <map> 8 //#include<unordered_map> 9 #include <vector> 10 #include <stack> 11 #include <set> 12 #include <string.h>//strstr substr strcat 13 #include <string> 14 #include <time.h>// srand(((unsigned)time(NULL))); Seed n=rand()%10 - 0~9; 15 #include <cmath> 16 #include <deque> 17 #include <queue>//priority_queue<int, vector<int>, greater<int> > q;//less 18 #include <vector>//emplace_back 19 //#include <math.h> 20 #include <cassert> 21 #include <iomanip> 22 //#include <windows.h>//reverse(a,a+len);// ~ ! ~ ! floor 23 #include <algorithm>//sort + unique : sz=unique(b+1,b+n+1)-(b+1);+nth_element(first, nth, last, compare) 24 using namespace std;//next_permutation(a+1,a+1+n);//prev_permutation 25 //****************** 26 clock_t __START,__END; 27 double __TOTALTIME; 28 void _MS(){__START=clock();} 29 void _ME(){__END=clock();__TOTALTIME=(double)(__END-__START)/CLOCKS_PER_SEC;cout<<"Time: "<<__TOTALTIME<<" s"<<endl;} 30 //*********************** 31 #define rint register int 32 #define fo(a,b,c) for(rint a=b;a<=c;++a) 33 #define fr(a,b,c) for(rint a=b;a>=c;--a) 34 #define mem(a,b) memset(a,b,sizeof(a)) 35 #define pr printf 36 #define sc scanf 37 #define ls rt<<1 38 #define rs rt<<1|1 39 typedef pair<int,int> PII; 40 typedef vector<int> VI; 41 typedef unsigned long long ull; 42 typedef long long ll; 43 typedef double db; 44 const db E=2.718281828; 45 const db PI=acos(-1.0); 46 const ll INF=(1LL<<60); 47 const int inf=(1<<30); 48 const db ESP=1e-9; 49 const int mod=(int)1e9+7; 50 const int N=(int)1e5+10; 51 52 int n; 53 ll val[N]; 54 ll _val[N]; 55 ll er[66]; 56 //========================================================================================= 57 vector<vector<int> >G(N),GG(N); 58 59 bool cmp(int a,int b) 60 { 61 return val[a]-_val[a]>val[b]-_val[b]; 62 } 63 64 ll pre(int v,int u) 65 { 66 int sz=G[v].size(); 67 for(int i=0;i<sz;++i) 68 { 69 int to=G[v][i]; 70 if(to!=u) 71 { 72 GG[v].push_back(to); 73 val[v]+=pre(to,v); 74 } 75 } 76 return val[v]; 77 } 78 79 ll st,max_; 80 int cnt; 81 82 void cut(int u,int fa) 83 { 84 if(val[u]-_val[u]<=st)return; 85 int sz=G[u].size(); 86 for(int i=0;i<sz;++i) 87 { 88 if(val[u]-_val[u]<=st)return; 89 int to=G[u][i]; 90 if(to!=fa) 91 cut(to,u),_val[u]+=_val[to]; 92 } 93 if(val[u]-_val[u]<=st)return; 94 sort(GG[u].begin(),GG[u].end(),cmp); 95 sz=GG[u].size(); 96 for(int i=0;i<sz;++i) 97 { 98 int to=GG[u][i]; 99 if(val[u]-_val[u]<=st) 100 return; 101 cnt++; 102 _val[u]+=val[to]-_val[to]; 103 } 104 } 105 106 ll get(int k) 107 { 108 st=er[50]; 109 for(int i=50;i>=1;--i) 110 { 111 if(st-er[i]<max_)continue; 112 for(int j=0;j<=n;++j)_val[j]=0; 113 cnt=1;//根节点我手动切 114 st-=er[i]; 115 cut(1,0); 116 if(cnt>k) 117 st+=er[i]; 118 } 119 return st; 120 } 121 int TOT=0; 122 123 void solve() 124 { 125 pr("Case #%d: ",++TOT); 126 int k; 127 sc("%d%d",&n,&k); 128 for(int i=1;i<=n;++i)G[i].clear(),GG[i].clear(); 129 for(int i=1;i<n;++i) 130 { 131 int u,v; 132 sc("%d%d",&u,&v); 133 G[u].push_back(v); 134 G[v].push_back(u); 135 } 136 max_=0; 137 for(int i=1;i<=n;++i)sc("%lld",&val[i]),max_=max(max_,val[i]); 138 pre(1,0); 139 pr("%lld ",get(k)); 140 } 141 142 int main() 143 { 144 er[1]=1; 145 for(int i=2;i<=65;++i)er[i]=er[i-1]*2;//,pr("%d: %lld ",i,er[i]); 146 int T; 147 sc("%d",&T); 148 while(T--)solve(); 149 return 0; 150 } 151 152 /**************************************************************************************/