poj1741(树上点分治)

题解:树上分治就是一直找重心,然后计算经过重心点的答案有多少,接着再把重心这个点删除掉然后接着在对应子树上接着重复上面步骤直到没有孩子结点。

我是根据下面这篇博客学习的

https://blog.csdn.net/qq_31759205/article/details/75579558

#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
#include<cstdio>
#include<cmath>
#include<set>
#include<map>
#include<cstdlib>
#include<ctime>
#include<stack>
#include<bitset>
using namespace std;
#define mes(a,b) memset(a,b,sizeof(a))
#define rep(i,a,b) for(int i = a; i <= b; i++)
#define dec(i,a,b) for(int i = b; i >= a; i--)
#define pb push_back
#define fi first
#define se second
#define ls rt<<1
#define rs rt<<1|1
#define lson ls,L,mid
#define rson rs,mid+1,R
#define lowbit(x) x&(-x)
typedef double db;
typedef long long int ll;
typedef pair<int,int> pii;
typedef unsigned long long ull;
const ll inf = 0x3f3f3f3f;
const int mx = 1e4+5;
const int mod = 1e9+7;
const int x_move[] = {1,-1,0,0,1,1,-1,-1};
const int y_move[] = {0,0,1,-1,1,-1,1,-1};
int n,m,len,sum;
int s[mx];
int dp[mx];
int maxson[mx];
int sz[mx];
bool vis[mx];
vector<pii >g[mx];
int root;
void get_root(int u,int fa){
	maxson[u] = 0;
	sz[u] = 1;
	for(int i = 0; i < g[u].size(); i++){
		int v = g[u][i].fi;
		if(v==fa||vis[v]) continue;
		get_root(v,u);
		sz[u] += sz[v];
		maxson[u] = max(maxson[u],sz[v]);
	}
	maxson[u] = max(maxson[u],sum-sz[u]);
	if(!root||maxson[u]<maxson[root]) root = u;
}
void calc_dis(int u,int fa){
	s[len++] = dp[u];
	sz[u] = 1;
	for(int i = 0; i < g[u].size(); i++){
		int v = g[u][i].fi;
		if(v==fa||vis[v]) continue;
		dp[v] = dp[u] + g[u][i].se;
		calc_dis(v,u);
		sz[u] += sz[v];
	}
}
int calc(int root,int m){
	dp[root] = 0;
	len = 0;
	calc_dis(root,0);
	sort(s,s+len);
	int ans = 0;
	int r = len-1;
	for(int i = 0; i < r; ){
		if(s[i]+s[r]>m) r--;
		else ans += r-i,i++;
	}
	return ans;
}
int get_ans(int u){
	vis[u] = 1;
	int ans = calc(u,m);
	for(int i = 0; i < g[u].size(); i++){
		int v = g[u][i].fi;
		if(vis[v]) continue;
		int w = g[u][i].se;
		ans -= calc(v,m-2*w);
		sum = sz[v];
		get_root(v,root = 0);
		ans += get_ans(root);
	}
	return ans;
}
int main(){
	//freopen("test.in","r",stdin);
	//freopen("test.out","w",stdout);
	maxson[0] = inf;
	int t,q,ca = 1;
	while(~scanf("%d%d",&n,&m))	{
		if(n==0&&m==0)
			break;
		for(int i = 1; i <= n; i++)
			g[i].clear(),vis[i] = 0;
		for(int i = 2; i <= n; i++){
			int u,v,w;
			scanf("%d%d%d",&u,&v,&w);
			g[u].pb(make_pair(v,w));
			g[v].pb(make_pair(u,w));
		}
		sum = n;
		root = 0;get_root(1,0);
		printf("%d\n",get_ans(root));
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/a1325136367/article/details/81101083