[IOI2011]Race
race
点分治
题目链接:https://www.luogu.org/problemnew/show/P4149;
在点分治过程中维护一下当层最小值即可,dfs一遍判断 路径权值 为v(v<=k)的路径最小数量g[v];
然后求下g[k-v]+g[v]的最小数量,更新下答案即可;
代码
1 #include<iostream> 2 #include<cstdio> 3 using namespace std; 4 const int M=200009; 5 const int N=1000009; 6 int n,k,num=0,tot=0,top=0,ans=1e9; 7 int size,minn,rt; 8 int head[M],b[M],g[N],p[M],c[M],siz[M],dep[M]; 9 struct P{int to,ne,w;}e[M<<1]; 10 bool vis[M]; 11 int read(){ 12 int rex=0,f=1;char ch=getchar(); 13 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 14 while(ch>='0'&&ch<='9'){rex=rex*10+ch-'0';ch=getchar();} 15 return rex*f; 16 } 17 void getrt(int u,int fa){ 18 int ma=0;siz[u]=1; 19 for(int i=head[u];i;i=e[i].ne){ 20 int v=e[i].to;if(v==fa||vis[v])continue; 21 getrt(v,u); 22 siz[u]+=siz[v];ma=max(ma,siz[v]); 23 } 24 ma=max(ma,size-siz[u]); 25 if(ma<minn){minn=ma,rt=u;} 26 } 27 void dfs(int u,int fa,int w){ 28 if(w>k)return; 29 b[++tot]=w;dep[u]=dep[fa]+1;c[tot]=dep[u]; 30 for(int i=head[u];i;i=e[i].ne){ 31 int v=e[i].to; 32 if(v!=fa&&!vis[v])dfs(v,u,w+e[i].w); 33 } 34 } 35 void get(int u,int fa,int w){ 36 tot=0; 37 dep[fa]=0; 38 dfs(u,fa,w); 39 for(int i=1;i<=tot;++i){ 40 ans=min(ans,c[i]+g[k-b[i]]); 41 p[++top]=b[i]; 42 } 43 for(int i=1;i<=tot;++i)g[b[i]]=min(g[b[i]],c[i]); 44 } 45 void work(int u){ 46 vis[u]=1;top=0; 47 for(int i=head[u];i;i=e[i].ne){ 48 int v=e[i].to; 49 if(!vis[v])get(v,u,e[i].w); 50 } 51 for(int i=1;i<=top;++i)g[p[i]]=1e9; 52 for(int i=head[u];i;i=e[i].ne){ 53 int v=e[i].to;if(vis[v])continue; 54 minn=1e9,size=siz[u]; 55 getrt(v,0); 56 work(rt); 57 } 58 } 59 int main(){ 60 n=read(),k=read(); 61 for(int i=1,u,v,w;i<n;++i){ 62 u=read()+1,v=read()+1,w=read(); 63 e[++num]=(P){v,head[u],w};head[u]=num; 64 e[++num]=(P){u,head[v],w};head[v]=num; 65 } 66 for(int i=1;i<=k;++i)g[i]=1e9; 67 minn=1e9,size=n; 68 getrt(1,0); 69 work(rt); 70 if(ans==1e9)ans=-1; 71 printf("%d",ans); 72 return 0; 73 }