BZOJ 2599: [IOI2011]Race(点分治板题)

我也就只会做做板题了…

记得清零数组的时候子树遍历清零,否则会T

CODE

#include<bits/stdc++.h>
using namespace std;
inline void read(int &num) {
	char ch; int flg = 1; while(!isdigit(ch=getchar()))if(ch=='-')flg = -flg;
	for(num=0; isdigit(ch); num=num*10+ch-'0', ch=getchar()); num*=flg;
}
const int MAXN = 200005;
const int MAXK = 1000005;
int n, k, fir[MAXN], cnt;
struct edge { int to, nxt, w; }e[MAXN<<1];
inline void link(int u, int v, int ww) {
	e[++cnt] = (edge){ v, fir[u], ww }, fir[u] = cnt;
}
bool ban[MAXN];
int Get_Size(int x, int ff) {
	int re = 1;
	for(int v, i = fir[x]; i; i = e[i].nxt)
		if(!ban[v=e[i].to] && v != ff) re += Get_Size(v, x);
	return re;
}
int Get_Root(int x, int ff, int Size, int &G) {
	int re = 1; bool flg = true;
	for(int v, i = fir[x]; i; i = e[i].nxt)
		if(!ban[v=e[i].to] && v != ff) {
			int temp = Get_Root(v, x, Size, G); re += temp;
			if(temp<<1 > Size) flg = 0;
		}
	if(Size-re<<1 > Size) flg = 0;
	if(flg) G = x;
	return re;
}
int st[MAXN][2], top, Ans;
void Count(int x, int ff, int dep, int dis) {
	if(dis > k) return;
	++top, st[top][0] = dep, st[top][1] = dis;
	for(int v, i = fir[x]; i; i = e[i].nxt)
		if(!ban[v=e[i].to] && v != ff)
			Count(v, x, dep+1, dis+e[i].w);
}
int f[MAXK];
void Clear(int x, int ff, int dis) {
	if(dis > k) return;
	f[dis] = n;
	for(int v, i = fir[x]; i; i = e[i].nxt)
		if(!ban[v=e[i].to] && v != ff)
			Clear(v, x, dis+e[i].w);
}
inline void Solve(int x) {
	f[0] = 0;
	for(int v, i = fir[x]; i; i = e[i].nxt)
		if(!ban[v=e[i].to]) {
			Count(v, x, 1, e[i].w);
			for(int j = 1; j <= top; ++j)
				Ans = min(Ans, st[j][0] + f[k-st[j][1]]);
			while(top) f[st[top][1]] = min(f[st[top][1]], st[top][0]), --top;
		}
	Clear(x, 0, 0);
}
int TDC(int x) {
	int Size = Get_Size(x, 0);
	Get_Root(x, 0, Size, x);
	Solve(x); ban[x] = 1;
	for(int v, i = fir[x]; i; i = e[i].nxt)
		if(!ban[v=e[i].to]) TDC(v);
}

int main() {
	read(n), read(k); Ans = n;
	for(int i = 1, x, y, z; i < n; ++i)
		read(x), read(y), read(z), link(x+1, y+1, z), link(y+1, x+1, z);
	for(int i = 1; i <= k; ++i) f[i] = n;
	TDC(1);
	printf("%d
", Ans < n ? Ans : -1);
}
原文地址:https://www.cnblogs.com/Orz-IE/p/12039290.html