bzoj 2599 [IOI2011]Race (点分治)
【题意】
问树中长为k的路径中包含边数最少的路径所包含的边数。
【思路】
统计经过根的路径。假设当前枚举到根的第S个子树,若x属于S子树,则有:
ans<-dep[x]+min{ dep[y] },y属于前S-1个子树,dis[x]<=K
所以只需要用一个数组t[len]记录前S-1棵子树中长度为len的最少边数即可。t只用开到K的最大值。
然后分治处理子树。
【代码】
1 #include<set> 2 #include<cmath> 3 #include<queue> 4 #include<vector> 5 #include<cstdio> 6 #include<cstring> 7 #include<iostream> 8 #include<algorithm> 9 #define trav(u,i) for(int i=front[u];i;i=e[i].nxt) 10 #define FOR(a,b,c) for(int a=(b);a<=(c);a++) 11 using namespace std; 12 13 typedef long long ll; 14 const int N = 1e6+10; 15 const int inf = 1e9; 16 17 ll read() { 18 char c=getchar(); 19 ll f=1,x=0; 20 while(!isdigit(c)) { 21 if(c=='-') f=-1; c=getchar(); 22 } 23 while(isdigit(c)) 24 x=x*10+c-'0',c=getchar(); 25 return x*f; 26 } 27 28 struct Edge { 29 int v,w,nxt; 30 }e[N<<1]; 31 int en=1,front[N]; 32 void adde(int u,int v,int w) 33 { 34 e[++en]=(Edge){v,w,front[u]}; front[u]=en; 35 } 36 37 int l1,l2; 38 int t[N],dep[N],dis[N],ans=inf,list[N]; 39 int vis[N],siz[N],rt,f[N],size,n,K; 40 41 void getroot(int u,int fa) 42 { 43 siz[u]=1; f[u]=0; 44 trav(u,i) if(e[i].v!=fa&&!vis[e[i].v]){ 45 int v=e[i].v; 46 getroot(v,u); 47 siz[u]+=siz[v]; 48 f[u]=max(f[u],siz[v]); 49 } 50 f[u]=max(f[u],size-siz[u]); 51 if(f[u]<f[rt]) rt=u; 52 } 53 void dfs(int u,int fa) 54 { 55 list[++l1]=u; 56 trav(u,i) if(e[i].v!=fa&&!vis[e[i].v]) { 57 int v=e[i].v; 58 dis[v]=dis[u]+e[i].w; 59 dep[v]=dep[u]+1; 60 dfs(v,u); 61 } 62 } 63 void solve(int u) 64 { 65 vis[u]=1; t[0]=0; 66 l1=l2=0; 67 trav(u,i) if(!vis[e[i].v]) { 68 int v=e[i].v; 69 dep[v]=1; dis[v]=e[i].w; 70 dfs(v,-1); 71 FOR(j,l2+1,l1) { 72 if(dis[list[j]]<=K) 73 ans=min(ans,dep[list[j]]+t[K-dis[list[j]]]); 74 } 75 FOR(j,l2+1,l1) 76 if(dis[list[j]]<=K) t[dis[list[j]]]=min(t[dis[list[j]]],dep[list[j]]); 77 l2=l1; 78 } 79 FOR(i,0,l1) t[dis[list[i]]]=inf; 80 trav(u,i) if(!vis[e[i].v]) { 81 int v=e[i].v; rt=0; 82 getroot(v,-1); size=siz[v]; 83 solve(rt); 84 } 85 } 86 87 int main() 88 { 89 freopen("in.in","r",stdin); 90 freopen("out.out","w",stdout); 91 n=read(),K=read(); 92 int u,v,w; 93 FOR(i,1,n-1) { 94 u=read()+1,v=read()+1,w=read(); 95 adde(u,v,w),adde(v,u,w); 96 } 97 FOR(i,1,K) t[i]=n; 98 size=f[0]=ans=n; 99 getroot(1,-1); 100 solve(rt); 101 if(ans==n) puts("-1"); 102 else printf("%d\n",ans); 103 return 0; 104 }
posted on 2016-03-27 10:32 hahalidaxin 阅读(290) 评论(0) 编辑 收藏 举报