BZOJ2599: [IOI2011]Race
n<=200000的边权树上问长度=K<=1000000的链中边数最少的。
点分治。开个桶统计各个长度的答案。
1 #include<string.h> 2 #include<stdlib.h> 3 #include<stdio.h> 4 #include<math.h> 5 #include<algorithm> 6 //#include<bitset> 7 //#include<queue> 8 //#include<iostream> 9 using namespace std; 10 11 int n,K; 12 #define maxn 200011 13 #define maxk 1000011 14 struct Edge{int to,v,next;}edge[maxn<<1]; int first[maxn],le=2; 15 void in(int x,int y,int v) {Edge &e=edge[le]; e.to=y; e.v=v; e.next=first[x]; first[x]=le++;} 16 void insert(int x,int y,int v) {in(x,y,v); in(y,x,v);} 17 18 int size[maxn]; bool die[maxn]; 19 void getsize(int x,int fa) 20 { 21 size[x]=1; 22 for (int i=first[x];i;i=edge[i].next) 23 { 24 const Edge &e=edge[i]; if (e.to==fa || die[e.to]) continue; 25 getsize(e.to,x); size[x]+=size[e.to]; 26 } 27 } 28 29 int getroot(int x,int fa,int tot) 30 { 31 for (int i=first[x];i;i=edge[i].next) 32 { 33 const Edge &e=edge[i]; if (e.to==fa || die[e.to]) continue; 34 if (size[e.to]*2>tot) return getroot(e.to,x,tot); 35 } 36 return x; 37 } 38 39 int f[maxk]; 40 void calc(int x,int fa,int now,int cur) 41 { 42 if (now>K) return; 43 f[K]=min(f[K],f[K-now]+cur); 44 for (int i=first[x];i;i=edge[i].next) 45 { 46 const Edge &e=edge[i]; if (e.to==fa || die[e.to]) continue; 47 calc(e.to,x,now+e.v,cur+1); 48 } 49 } 50 51 void gao(int x,int fa,int now,int v,bool op) 52 { 53 if (now>K) return; 54 if (op) f[now]=min(f[now],v); 55 else (now!=K && (f[now]=0x3f3f3f3f)); 56 for (int i=first[x];i;i=edge[i].next) 57 { 58 const Edge &e=edge[i]; if (e.to==fa || die[e.to]) continue; 59 gao(e.to,x,now+e.v,v+1,op); 60 } 61 } 62 63 void cd(int x) 64 { 65 die[x]=1; f[0]=0; 66 for (int i=first[x];i;i=edge[i].next) 67 { 68 const Edge &e=edge[i]; if (die[e.to]) continue; 69 calc(e.to,x,e.v,1); gao(e.to,x,e.v,1,1); 70 } 71 for (int i=first[x];i;i=edge[i].next) 72 { 73 const Edge &e=edge[i]; if (die[e.to]) continue; 74 gao(e.to,x,e.v,0,0); 75 } 76 for (int i=first[x];i;i=edge[i].next) 77 { 78 const Edge &e=edge[i]; if (die[e.to]) continue; 79 getsize(e.to,x); cd(getroot(e.to,x,size[e.to])); 80 } 81 } 82 83 int main() 84 { 85 scanf("%d%d",&n,&K); 86 for (int i=1,x,y,v;i<n;i++) 87 { 88 scanf("%d%d%d",&x,&y,&v); x++; y++; 89 insert(x,y,v); 90 } 91 getsize(1,0); 92 for (int i=1;i<=K;i++) f[i]=0x3f3f3f3f; 93 cd(getroot(1,0,size[1])); 94 printf("%d\n",f[K]==0x3f3f3f3f?-1:f[K]); 95 return 0; 96 }