poj1741Tree 树的分治 树形dp 男人八题....

poj1741Tree


没有思路的话就看看漆子超的论文


//重心 距离 排序 统计 

//http://www.2cto.com/kf/201208/149839.html#comment_iframe
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#include<algorithm>
using namespace std;

#define MAXN 10010

int N,K;
struct Node{					//邻接表 
    int v, w;
    Node(int v_, int w_){
        v= v_, w= w_;
    }
};
vector<Node>son[MAXN];

int vis[MAXN];			//标记是否访问过

int num[MAXN];					//num[i]在以i为根的子树中节点的数量 
int size_of_n[MAXN];			//删除n之后得到子树中子树节点的最大值 
int mi,root;
void dfssize(int n, int fa) //处理子树的大小  
{ 
    num[n] = 1; 
    size_of_n[n] = 0; 
    int len=son[n].size();
    for(int i=0;i<len;i++)
    {
    	int k = son[n][i].v; 
        if(k != fa && !vis[k]) 
        { 
            dfssize(k, n); 
            num[n] += num[k]; 
            if(num[k] > size_of_n[n]) size_of_n[n] = num[k]; 
        }
    }
}

void dfsroot(int r, int n, int fa) //求重心  
{ 
    if(num[r] - num[n] > size_of_n[n]) size_of_n[n] = num[r] - num[n]; 
    if(size_of_n[n] < mi) mi = size_of_n[n], root = n; 
    int len=son[n].size();
    for(int i=0;i<len;i++)
    { 
        int k = son[n][i].v; 
        if(k != fa && !vis[k]) dfsroot(r, k, n); 
    } 
} 

int depth[MAXN],S;
void dfs_depth(int n,int fa,int dis)
{
	int i,k,len=son[n].size();
	depth[++S]=dis;
	for(i=0;i<len;i++){
		k=son[n][i].v;
		if(!vis[k]&&k!=fa)	dfs_depth(k,n,dis+son[n][i].w);
	}
}
/*
对depth中的距离排序后算出有多少对数字相加小于K,
dis的作用:dis==0时dfs_depth求出的距离都是以n为根并且不限制方向,
dis!=0时,假设dis为n到某个儿子的边的长度,那么求出来的所有距离都以这条边为第一步  
也就是相当于限定了方向
*/
int NUM(int n,int dis){
	S=0;
	dfs_depth(n,-1,dis);
	sort(depth+1,depth+1+S);
	int i=1,j=S,ret=0;
	while(i<j){
		while(depth[j]+depth[i]>K&&j>i)	j--;
		ret+=j-i;
		i++;
	}
	return ret;
}

int dfs_ans(int n){
	mi = N; 
    dfssize(n, 0);
    dfsroot(n, n, 0);
	int SUM=0;
	SUM+=NUM(root,0);
	vis[root]=1;
	int len=son[root].size();
	for(int i=0;i<len;i++){
		int k=son[root][i].v;
		if(vis[k])	continue;
		SUM-=NUM(k,son[root][i].w);
		int temp=root;SUM+=dfs_ans(k);root=temp;
	}
	return SUM;
}

int main()
{
	int i,j,k,u,v,l;
	while(scanf("%d%d",&N,&K),N||K)
	{
		for(i=1;i<=N;i++){son[i].clear();}
		for(i=1;i<=N-1;i++){
			scanf("%d%d%d",&u,&v,&l);
			son[u].push_back(Node(v,l));
			son[v].push_back(Node(u,l));
		}
		memset(vis,0,sizeof(vis));
		printf("%d\n",dfs_ans(1));
	}
	return 0;
}


/*

5 4
1 2 3
1 3 1
1 4 2
3 5 1

6 4
1 2 3
1 3 1
1 4 2
3 5 1
3 6 1

3 4
1 2 3
2 3 2

*/




你可能感兴趣的:(poj1741Tree 树的分治 树形dp 男人八题....)