poj 1741(树的点分治)

Tree

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树的点分治 参考了漆子超的论文 以及多位大佬的博客 

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cmath>
  4 #include<cstring>
  5 #include<algorithm>
  6 #include<queue>
  7 #include<map>
  8 #include<set>
  9 #include<vector>
 10 #include<cstdlib>
 11 #include<stack>
 12 #include<string>
 13 #define eps 0.000000001
 14 typedef long long ll;
 15 typedef unsigned long long LL;
 16 using namespace std;
 17 const int INF=0x3f3f3f3f;
 18 const int N=100000+10;
 19 int son[N];
 20 int ans;
 21 int num;
 22 int p;
 23 int head[N];
 24 int vis[N];
 25 int minn;
 26 int root;
 27 int k;
 28 int dis[N];
 29 void init(){
 30     num=0;
 31     memset(vis,0,sizeof(vis));
 32     memset(head,-1,sizeof(head));
 33 }
 34 struct node{
 35     int to,next,w;
 36 }edge[N];
 37 void add(int u,int v,int w){
 38     edge[num].to=v;
 39     edge[num].w=w;
 40     edge[num].next=head[u];
 41     head[u]=num++;
 42 }
 43 void getroot(int x,int y,int n){
 44     son[x]=1;
 45     int maxx=0;
 46     for(int i=head[x];i!=-1;i=edge[i].next){
 47         int v=edge[i].to;
 48         if(v==y||vis[v])continue;
 49         getroot(v,x,n);
 50         son[x]=son[x]+son[v];
 51         maxx=max(maxx,son[v]);
 52     }
 53     maxx=max(maxx,n-son[x]);
 54     //cout<<maxx<<" "<<x<<endl;
 55     if(minn>maxx){
 56         minn=maxx;
 57         root=x;
 58     }
 59 }
 60 void getdeep(int x,int v0,int y){
 61     dis[p++]=y;
 62     for(int i=head[x];i!=-1;i=edge[i].next){
 63         int v=edge[i].to;
 64         if(v==v0||vis[v])continue;
 65         getdeep(v,x,y+edge[i].w);
 66     }
 67 }
 68 int cal(int x,int y){
 69     int res=0;
 70     p=0;
 71     getdeep(x,0,y);
 72     sort(dis,dis+p);
 73     int l=0;
 74     int r=p-1;
 75     while(l<r){
 76         if(dis[l]+dis[r]<=k){
 77             res=res+(r-l);
 78             l++;
 79         }
 80         else{
 81             r--;
 82         }
 83     }
 84     return res;
 85 }
 86 void work(int x){
 87     ans=ans+cal(x,0);
 88     //cout<<cal(x,0)<<" ";
 89    // cout<<endl;
 90     vis[x]=1;
 91     for(int i=head[x];i!=-1;i=edge[i].next){
 92         int v=edge[i].to;
 93         if(vis[v]==0){
 94             ans=ans-cal(v,edge[i].w);
 95             minn=INF;
 96             getroot(v,0,son[v]);
 97             work(root);
 98         }
 99     }
100 }
101 int main(){
102     int n;
103     while(scanf("%d%d",&n,&k)!=EOF){
104         if(n==0&&k==0)break;
105         init();
106         for(int i=0;i<n-1;i++){
107             int u,v,w;
108             scanf("%d%d%d",&u,&v,&w);
109             add(u,v,w);
110             add(v,u,w);
111         }
112         ans=0;
113         minn=INF;
114         getroot(1,-1,n);
115         //for(int i=1;i<=n;i++)cout<<son[i]<<" ";
116        // cout<<endl;
117        //cout<<root<<" "<<minn<<endl;
118         work(root);
119         cout<<ans<<endl;
120     }
121     return 0;
122 }
				
时间: 2024-10-20 08:44:25

poj 1741(树的点分治)的相关文章

poj 1741 树的点分治(入门)

Tree Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 18205   Accepted: 5951 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

POJ 1741 树的点分治

题目大意: 树上找到有多少条路径的边权值和>=k 这里在树上进行点分治,需要找到重心保证自己的不会出现过于长的链来降低复杂度 1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <vector> 5 #include <algorithm> 6 7 using namespace std; 8 #define N 10005 9 int n ,

POJ 1741 Tree (树上点分治)(楼教主男人八题之一)

题目地址:POJ 1741 树分治第一发! 树分治详情请看漆子超的国家集训队论文,论文传送门 树分治裸题. 代码如下: #include <iostream> #include <string.h> #include <math.h> #include <queue> #include <algorithm> #include <stdlib.h> #include <map> #include <set> #

POJ 1741 树分治(点分治模板题)

POJ 1741 题意:求一棵树中点对<=k的数量. 总结:点分治,搞不太懂..大概敲了一遍 #include<iostream> #include<cstdio> #include<cstdlib> #include<algorithm> #include<cstring> #include<string> #include<cmath> #include<queue> #include<stac

POJ 1741 树分治

题目链接[http://poj.org/problem?id=1741] 题意: 给出一颗树,然后寻找点对(u,v)&&dis[u][v] < k的对数. 题解: 这是一个很经典的树分治的题.假设我们选择了一个参考点u,那么对于不同的点对(u,v),(u , v)之间的路径有两种情况,经过点u,和不经过点u,加入我算出了没有经过点u的对数,然后把经过点u的加起来就是答案了,很简单,这就是分治的思想.具体看代码. #include<cstdio> #include<c

POJ 1741 树上的点分治

题目大意: 找到树上点对间距离不大于K的点对数 这是一道简单的练习点分治的题,注意的是为了防止点分治时出现最后分治出来一颗子树为一条直线,所以用递归的方法求出最合适的root点 1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <vector> 5 #include <algorithm> 6 7 using namespace std; 8 #de

树的点分治 (poj 1741, 1655(树形dp))

poj 1655:http://poj.org/problem?id=1655 题意: 给无根树,  找出以一节点为根,  使节点最多的树,节点最少. 题解:一道树形dp,先dfs 标记 所有节点的子树的节点数. 再dfs  找出以某节点为根的最大子树,节点最少. 复杂度(n) /***Good Luck***/ #define _CRT_SECURE_NO_WARNINGS #include <iostream> #include <cstdio> #include <cs

poj 1741 楼教主男人八题之一:树分治

http://poj.org/problem?id=1741 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

poj 1741 Tree(树的点分治)

poj 1741 Tree(树的点分治) 给出一个n个结点的树和一个整数k,问有多少个距离不超过k的点对. 首先对于一个树中的点对,要么经过根结点,要么不经过.所以我们可以把经过根节点的符合点对统计出来.接着对于每一个子树再次运算.如果不用点分治的技巧,时间复杂度可能退化成\(O(n^2)\)(链).如果对于子树重新选根,找到树的重心,就一定可以保证时间复杂度在\(O(nlogn)\)内. 具体技巧是:首先选出树的重心,将重心视为根.接着计算出每个结点的深度,以此统计答案.由于子树中可能出现重复

【POJ 1741】 Tree (树的点分治)

Tree 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)