poj1741 Tree 树的点分冶


Tree

Time Limit: 1000MS   Memory Limit: 30000K
Total Submissions: 13528   Accepted: 4350

Description

Give a tree with n vertices,each edge has a length(positive integer less than 1001).

Define dist(u,v)=The min distance between node u and v.

Give an integer k,for every pair (u,v) of vertices is called valid if and only if dist(u,v) not exceed k.

Write a program that will count how many pairs which are valid for a given tree.

Input

The input contains several test cases. The first line of each test case contains two integers n, k. (n<=10000) The following n-1 lines each contains three integers u,v,l, which means there is an edge between node u and v of length l.

The last test case is followed by two zeros.

Output

For each test case output the answer on a single line.

Sample Input

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

Sample Output

8

Source

[email protected]

[Submit]   [Go Back]   [Status]  
[Discuss

题意,是给出一个树,要求距离小于k的结点对数,树的点分冶。

由容质原理,一棵树的结点对数为

没有限制的 - ∑端点落在同一颗子树上的. 上述两个过程是一样的, 于是只考虑没有限制的怎么做。所以用树的点分冶,统计经过树根的个数,然后,分别统计经过,每个结点的个数,反正,对于一棵树,不论以谁看成是根结点,都是可以的。那么,找那个结点作为根最好呢,当然是树的重心。

1.求树的重心,就是有个结点,以它为根的话,它所有的子树的最大结点最小,用树形dp的做法,可以在o(n)复杂度内解决。

dp[i]表示,以i为根,子树的结点数的最大值。则dp[i] = max(dp[j],总结点数
- nodes[i]);j是i的子树,nodes[i]表示i为根,所有的结点数。以i为根的时候,还要考虑到我们是以i的根搜下来的,所以要用总是减去i为根的总结点数,就是以i的父结点为i子结点时的总个数。

2.统计以i为根没有限制的对数,我们把所以的i的树上的结点到i的距离,用一个深搜统计起来,再加入一个数组,排下序,转化成了,要在一个排了序的数组a1
a2  ....  an 求出ai + a[j] <=k(j > i)的个数,这里,就可以用o(n)方法统计出来。枚举每个i,因为a[i]是递增的,所以j就是递减的。由于j只会减不会增,所以,是线性算法。端点落在同一颗子树上的和没有限制的是同一个问题,只要以子结点为根统计,就可以了。

总的说一下,由于每次是以重心为根,那么子结点的个数一定就是减少了一半的,所以在log(n)可以解决,对于一棵树,由于,每个树都要统计排序,复杂度为n
* log(n),所以总的复杂度为o(n * log(n) * log(n));也就可以过了。

#define N 10050
#define M 100005
#define maxn 205
#define MOD 1000000000000000007
int n,m,k,u,v,l,center,all,num,nodes[N],dp[N],dep[N];
ll ans;
bool vis[N];
vector<pii> p[N];
vector<int> depV;
void findRoot(int root,int fa){
    nodes[root] = 1;dp[root] = 0;
    FI(p[root].size()){
        int g = p[root][i].first;
        if(g != fa && !vis[g]){
            findRoot(g,root);
            nodes[root] += nodes[g];
            dp[root] = max(dp[root],nodes[g]);
        }
    }
    dp[root] = max(dp[root],all - nodes[root]);
    if(dp[root] < num){
        num = dp[root];center = root;
    }
}
int getRoot(int root,int sn){
    num = INF;all = sn;center = root;
    findRoot(root,-1);
    return center;
}
void getDp(int root,int fa){
    nodes[root] = 1;
    depV.push_back(dep[root]);
    FI(p[root].size()){
        int g = p[root][i].first;
        if(g != fa && !vis[g]){
            dep[g] = dep[root] + p[root][i].second;
            getDp(g,root);
            nodes[root] += nodes[g];
        }
    }
}
ll cal(int root,bool isfirst){
    depV.clear();
    if(isfirst)
        dep[root] = 0;
    getDp(root,-1);
    sort(depV.begin(),depV.end());
    ll sum = 0;
    for(int i = 0,j = depV.size() - 1;i < depV.size();i++){
        while(j>i && depV[i] + depV[j] > k) j--;
        if(j > i)
            sum += (ll)(j - i);
    }
    return sum;
}
int work(int root,int fa){
    vis[root] = true;
    ans += cal(root,true);
    FI(p[root].size()){
        int g = p[root][i].first;
        if(g != fa && !vis[g]){
            ans -= cal(g,false);
            work(getRoot(g,nodes[g]),-1);
        }
    }
}
int main()
{
    while(S2(n,k)!=EOF && n + k)
    {
        ans = 0;
        FI(n) p[i + 1].clear(),vis[i + 1] = false;
        FI(n-1){
            S2(u,v);S(l);
            p[u].push_back(mp(v,l));
            p[v].push_back(mp(u,l));
        }
        work(getRoot(1,n),-1);
        printf("%lld\n",ans);
    }
    return 0;
}

Home Page   Go
Back
  To top

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-09-29 18:08:31

poj1741 Tree 树的点分冶的相关文章

hdu 5314 Happy King 树点分冶 树状数组

Happy King Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others) Total Submission(s): 434    Accepted Submission(s): 79 Problem Description There are n cities and n?1 roads in Byteland, and they form a tree. The citie

JQuery Easy Ui (Tree树)详解

在这里沉重悼念我辛辛苦苦写了4个小时的文章,因为我的失误,没保存,而夭折啦..... 我的痛苦谁能懂? 哎~~~~  吃一见长一智吧! 么的办法啊! 但是,但是!我狠了狠心,咬了咬牙!我决定,再写一遍!!! 谁知道哭的表情怎么写! 我已经无法用言语表达我此时此刻的沉重心情了! (以下内容,身为菜鸟的我是用颤抖的双手敲出来的,忘同志们珍惜!!!!) 记得4个小时之前,我写过一个随笔,它的内容是这样的: 每次写博客,都喜欢在前面和大家分享一些东西,今天要分享的是一个小故事: 一个世界著名的大酒店正在

JQuery Easy Ui (Tree树)详解(转)

JQuery Easy Ui (Tree树)详解(转) 第一讲:JQuery Easy Ui到底是什么呢? 首先咱们知道JQuery是对Java Script的封装,是一个js库,主要提供的功能是选择器,属性修改和事件绑定等等.. JQuery ui是在jQuery的基础上,利用jQuery的扩展性,设计的插件. 那么JQuery Easy Ui到底是什么呢? 我的理解就是比JQuery ui更强大,同样都是实现绚丽的多功能效果! jQuery Easy UI的目的就是帮助Web开发者更轻松的打

hdu 5452(树链刨分)

看到题目,想了挺长时间,发现不会,然后看着样子像是树上成段操作,所以查了下树链刨分,结果真的就是这个东西... Minimum Cut Time Limit: 3000/2000 MS (Java/Others)    Memory Limit: 65535/102400 K (Java/Others)Total Submission(s): 453    Accepted Submission(s): 180 Problem Description Given a simple unweigh

POJ 2763 Housewife Wind 树链拋分

一.前言 这破题WA了一天,最后重构还是WA,最后通过POJ讨论版得到的数据显示,我看上去是把某个变量写错了..于是,还是低级错误背锅啊....代码能力有待进一步提升2333333 二.题意 某家庭主妇住在一棵树上,他的若干个孩子在树的若干个节点上有分布,主妇同学需要从某给定节点出发,飞到树上的制定节点,在过程中,边权可能会发生改变,问从当前节点到指定节点的边权和. 三.解法 树链拋分,点更新查区间. // #include<bits/stdc++.h> #include<iostrea

hdu 4863 Centroid of a Tree 树dp

代码来自baka.. #include<iostream> #include<cstdio> #include<cstring> #include<string> #include<algorithm> #include<map> #include<queue> #include<stack> #include<set> #include<cmath> #include<vecto

分冶算法思想

1.分冶算法思想是将一个计算复杂的问题分为规模较小,计算简单的问题,,然后综合各个小问题得到最终问题的答案. 2.分冶算法的执行过程 对于一个对魔为N的问题,若该问题可以容易的解决,则直接解决,否则执行下面的步骤. 将该分解为M个规模较小的子问题,子问题相互独立,并且与原问题形式相同. 递归的解这些问题, 然后,将各子问题的姐合并得到原问题的解. 3.分冶算法例子 java实现: package com.sjx.test1;import java.util.Scanner; public cla

SPOJ375 Query on a tree 树链剖分

SPOJ375  Query on a tree   树链剖分 no tags You are given a tree (an acyclic undirected connected graph) with N nodes, and edges numbered 1, 2, 3...N-1. We will ask you to perfrom some instructions of the following form: CHANGE i ti : change the cost of

HDU 3333 Turing Tree 树状数组 离线查询

题意: 给你一个数列,然后有n个查询,问你给定区间中不同数字的和是多少. 思路还是比较难想的,起码对于蒟蒻我来说. 将区间按照先右端点,后左端点从小到大排序之后,对于每个查询,我只要维护每个数字出现的最后一次就可以了(这个结论稍微想一下就可以证明是正确的). 然后就是简单的点更新,区间求和问题了- #include <cstdio> #include <cstring> #include <iostream> #include <map> #include