POJ1741 Tree
Posted autoint
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了POJ1741 Tree相关的知识,希望对你有一定的参考价值。
题意
Language:
Tree
Time Limit: 1000MS | Memory Limit: 30000K | |
Total Submissions: 32398 | Accepted: 10810 |
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.
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.
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
分析
点分治模板题。每次选择要处理的子树的重心,这样每个节点的处理不会超过\(O(\log n)\)次。
要路径长≤k,可以把节点放入按照距离根的距离排序,维护指针L,R,可以发现L从左到右扫描的过程中,恰好使得d[L]+d[R]≤k的R的范围是从右向左单调递减的,所以可以直接扫描处理。由于要排除同一子树内的节点之间的路径,所以要记录[L,R]与L处于同一子树内的节点的个数cnt[belong[L]]。那么L的答案就是R-L-cnt[belong[L]]。
时间复杂度\(O(n \log^2)\)
代码
值得一提的是,读入边的时候用快读会TLE,写成scanf
才能AC。大概是数据有问题……
#include<iostream>
#include<cstring>
#include<algorithm>
#define rg register
#define il inline
#define co const
template<class T>il T read(){
rg T data=0,w=1;rg char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') w=-1;ch=getchar();}
while(isdigit(ch)) data=data*10+ch-'0',ch=getchar();
return data*w;
}
template<class T>il T read(rg T&x) {return x=read<T>();}
typedef long long ll;
using namespace std;
co int N=1e4+1;
int n,k,s[N],Ans;
bool v[N],w[N];
int Head[N],Edge[N*2],Leng[N*2],Next[N*2],t;
int ans,pos;
int d[N],b[N],a[N],tot,cnt[N];
void dfs_find(int S,int x){
v[x]=1,s[x]=1;
int max_part=0;
for(int i=Head[x];i;i=Next[i]){
int y=Edge[i];
if(v[y]||w[y]) continue;
dfs_find(S,y);
s[x]+=s[y];
max_part=max(max_part,s[y]);
}
max_part=max(max_part,S-s[x]);
if(max_part<ans) ans=max_part,pos=x;
}
void dfs(int x){
v[x]=1;
for(int i=Head[x];i;i=Next[i]){
int y=Edge[i],z=Leng[i];
if(v[y]||w[y]) continue;
++cnt[b[a[++tot]=y]=b[x]];
d[y]=d[x]+z;
dfs(y);
}
}
bool cmp(int i,int j) {return d[i]<d[j];}
void work(int S,int x){
memset(v,0,sizeof v);
dfs_find(ans=S,x);
memset(d,0,sizeof d);
memset(cnt,0,sizeof cnt);
memset(v,0,sizeof v);
w[a[tot=1]=b[pos]=pos]=1;
++cnt[pos];
for(int i=Head[pos];i;i=Next[i]){
int y=Edge[i],z=Leng[i];
if(v[y]||w[y]) continue;
++cnt[a[++tot]=b[y]=y];
d[y]=z;
dfs(y);
}
sort(a+1,a+tot+1,cmp);
int l=1,r=tot;
--cnt[b[a[1]]];
while(l<r){
while(d[a[l]]+d[a[r]]>k) --cnt[b[a[r--]]];
Ans+=r-l-cnt[b[a[l]]];
--cnt[b[a[++l]]];
}
int now=pos;
for(int i=Head[now];i;i=Next[i]){
int y=Edge[i];
if(w[y]) continue;
work(s[y],y);
}
}
void add(int x,int y,int z){
Edge[++t]=y,Leng[t]=z;
Next[t]=Head[x],Head[x]=t;
}
void Tree(){
t=0;
memset(Head,0,sizeof Head);
for(int i=1,x,y,z;i<n;++i){
// read(x),read(y),read(z);
scanf("%d %d %d", &x, &y, &z);
add(x,y,z),add(y,x,z);
}
memset(w,0,sizeof w);
Ans=0;
work(n,1);
printf("%d\n",Ans);
}
int main(){
// freopen(".in","r",stdin),freopen(".out","w",stdout);
while(read(n)|read(k)) Tree();
return 0;
}
以上是关于POJ1741 Tree的主要内容,如果未能解决你的问题,请参考以下文章