IOI2011 Race [点分治]
题意
给一棵树,每条边有权。求一条简单路径,权值和等于 $K$,且边的数量最小。
点分治,求距离时带上经过边的数量即可。用的第一种写法(下面)。
食用淀粉质注意事项
1、 统计子树内答案的两种写法: 跟树形dp一样将某子树与前面的子树合并 或者是 考虑所有子树的答案再容斥,减去不合法的一棵子树内答案。
2、好好写求重心,千万不要写假!!!假淀粉害死人
注意每次遍历先初始化$f[x]=0$,要有子树大小$S$。
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 using namespace std; 5 const int N=200010; 6 const int M=1000010; 7 const int inf=0x3f3f3f3f; 8 int n,k,x,y,z,rt,f[N],size[N],ans=inf,S; 9 int dis[N],d[N],his[N],h[N],rec[M],t[N]; 10 bool vis[N]; 11 int head[N],to[N<<1],nxt[N<<1],w[N<<1],p; 12 inline int read() { 13 int re=0; char ch=getchar(); 14 while (ch<'0'||ch>'9') ch=getchar(); 15 while (ch>='0'&&ch<='9') re=re*10+ch-48,ch=getchar(); 16 return re; 17 } 18 inline void add(int x,int y,int z) { 19 to[++p]=y; nxt[p]=head[x]; w[p]=z; head[x]=p; 20 to[++p]=x; nxt[p]=head[y]; w[p]=z; head[y]=p; 21 } 22 void get_rt(int x,int fa) { 23 size[x]=1; f[x]=0;//here 24 for (int i=head[x]; i; i=nxt[i]) { 25 if (to[i]==fa || vis[to[i]]) continue; 26 get_rt(to[i],x); 27 size[x]+=size[to[i]]; 28 if (size[to[i]]>f[x]) f[x]=size[to[i]]; 29 } 30 f[x]=max(f[x],S-size[x]);//here 31 if (f[x]<f[rt]) rt=x; 32 } 33 void get_dis(int x,int fa) { 34 if (d[x]<=k) dis[++dis[0]]=d[x],his[dis[0]]=h[x]; 35 for (int i=head[x]; i; i=nxt[i]) { 36 if (to[i]==fa || vis[to[i]]) continue; 37 d[to[i]]=d[x]+w[i]; h[to[i]]=h[x]+1; 38 if (d[to[i]]<=k) get_dis(to[i],x); 39 } 40 } 41 void dfs(int x) { 42 vis[x]=1; int T=0; 43 for (int i=head[x]; i; i=nxt[i]) { 44 if (vis[to[i]]) continue; 45 dis[0]=0; d[to[i]]=w[i],h[to[i]]=1; get_dis(to[i],x); 46 for (int i=1; i<=dis[0]; i++) 47 if (~rec[k-dis[i]]) ans=min(ans,his[i]+rec[k-dis[i]]); 48 for (int i=1; i<=dis[0]; i++) 49 t[++T]=dis[i],rec[dis[i]]=~rec[dis[i]] ? min(rec[dis[i]],his[i]):his[i]; 50 } 51 while (T) rec[t[T--]]=-1; 52 for (int i=head[x]; i; i=nxt[i]) { 53 if (vis[to[i]]) continue; 54 S=size[to[i]]; f[rt=0]=inf; 55 get_rt(to[i],x); dfs(rt); 56 } 57 } 58 int main() { 59 n=read(); k=read(); 60 for (int i=1; i<n; i++) x=read()+1,y=read()+1,z=read(),add(x,y,z); 61 memset(rec,-1,sizeof rec); rec[0]=0; 62 S=n; f[rt=0]=inf; 63 get_rt(1,0); dfs(rt); 64 printf("%d\n",ans==inf ? -1:ans); 65 return 0; 66 }