[IOI2011]Race

I.[IOI2011]Race

思路:弱智淀粉质题。唯一缺点就是卡常,卡的要死要活

具体来说,只需要开出桶来(因为\(m\)最大只到\(10^6\),因此直接处理长度\(\leq m\)的路径存入桶中求\(\min\)即可。

代码:

#include<bits/stdc++.h>
using namespace std;
int n,m,dis[200100],head[200100],root,dep[200100],tp,sz[200100],msz[200100],SZ,ROOT,cnt,res=0x3f3f3f3f,buc[1000100];
bool vis[200100];
struct edge{
	int to,next,val;
}edge[400100];
void ae(int u,int v,int w){
	edge[cnt].next=head[u],edge[cnt].to=v,edge[cnt].val=w,head[u]=cnt++;
	edge[cnt].next=head[v],edge[cnt].to=u,edge[cnt].val=w,head[v]=cnt++;
}
void getroot(int x,int fa){
	sz[x]=1,msz[x]=0;
	for(int i=head[x];i!=-1;i=edge[i].next)if(!vis[edge[i].to]&&edge[i].to!=fa)getroot(edge[i].to,x),sz[x]+=sz[edge[i].to],msz[x]=max(msz[x],sz[edge[i].to]);
	msz[x]=max(msz[x],SZ-sz[x]);
	if(msz[x]<msz[ROOT])ROOT=x;
}
void getdis(int x,int fa,int DIS,int DEP){
	if(DIS>m)return;
	tp++,dep[tp]=DEP,dis[tp]=DIS;
	for(int i=head[x];i!=-1;i=edge[i].next)if(!vis[edge[i].to]&&edge[i].to!=fa)getdis(edge[i].to,x,DIS+edge[i].val,DEP+1);
}
void getans(int x){
	tp=0;
	for(int i=head[x];i!=-1;i=edge[i].next){
		if(vis[edge[i].to])continue;
		int las=tp;
		getdis(edge[i].to,x,edge[i].val,1);
		for(int j=las+1;j<=tp;j++)res=min(res,buc[m-dis[j]]+dep[j]);
		for(int j=las+1;j<=tp;j++)buc[dis[j]]=min(buc[dis[j]],dep[j]);
	}
	for(int i=1;i<=tp;i++)buc[dis[i]]=0x3f3f3f3f;
}
void solve(int x){
//	printf("%d\n",x);
	getans(x),vis[x]=true;
	for(int i=head[x];i!=-1;i=edge[i].next){
		if(vis[edge[i].to])continue;
		ROOT=0,SZ=sz[edge[i].to],getroot(edge[i].to,x),solve(ROOT);
	}
}
void read(int &x){
	x=0;
	char c=getchar();
	while(c>'9'||c<'0')c=getchar();
	while(c<='9'&&c>='0')x=(x<<3)+(x<<1)+(c^48),c=getchar();
}
int main(){
	read(n),read(m),memset(head,-1,sizeof(head)),memset(buc,0x3f3f3f3f,sizeof(buc)),buc[0]=0;
	for(int i=1,x,y,z;i<n;i++)read(x),read(y),read(z),ae(++x,++y,z);
	msz[0]=(SZ=n)+1,getroot(1,0),solve(ROOT);
	printf("%d\n",res==0x3f3f3f3f?-1:res);
	return 0;
}

原文地址:https://www.cnblogs.com/Troverld/p/14605773.html