1. 程式人生 > >IOI2011 Race [點分治]

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 }