您的位置:首页 > 其它

bzoj1468

2016-05-07 20:31 260 查看

1468: Tree

Time Limit: 10 Sec Memory Limit: 64 MB
Submit: 1023 Solved: 532
[Submit][Status][Discuss]

Description

给你一棵TREE,以及这棵树上边的距离.问有多少对点它们两者间的距离小于等于K

Input

N(n<=40000) 接下来n-1行边描述管道,按照题目中写的输入 接下来是k

Output

一行,有多少对点之间的距离小于等于k

Sample Input

7

1 6 13

6 3 9

3 5 7

4 1 3

2 4 20

4 7 2

10

Sample Output

5

HINT

Source

题解:

  点分治裸题,那么什么是点分治呢

  点分治

  1、求树的重心
  2、计算以当前重心为根的子树的答案
  3、去掉以当前重心儿子为根的子树的答案
  4、枚举每个儿子,分治

代码:

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
#define maxn 40005
using namespace std;
int n,k,i,j,tot,root,ans,L,all;
int pre[maxn*2],now[maxn],v[maxn*2],val[maxn*2],son[maxn],f[maxn];
int dist[maxn],data[maxn];
bool vis[maxn];
int read()
{
int x=0; char ch; bool bo=0;
while (ch=getchar(),ch<'0'||ch>'9') if (ch=='-') bo=1;
while (x=x*10+ch-'0',ch=getchar(),ch>='0'&&ch<='9');
if (bo) return -x; return x;
}
void ins(int a,int b,int c){
pre[++tot]=now[a]; now[a]=tot; v[tot]=b; val[tot]=c;
}
void get_root(int u,int fa)
{
son[u]=1; f[u]=0;
for (int p=now[u]; p; p=pre[p])
{
int vv=v[p];
if (vv==fa || vis[vv]) continue;
get_root(vv,u); son[u]+=son[vv];
f[u]=max(f[u],son[vv]);
}
f[u]=max(f[u],all-son[u]);
if (f[u]<f[root]) root=u;
}
void get_array(int u,int fa)
{
data[++L]=dist[u];
for (int p=now[u]; p; p=pre[p])
{
int vv=v[p];
if (vv!=fa&&!vis[vv])
dist[vv]=dist[u]+val[p],get_array(vv,u);
}
}
int calc(int u,int value)
{
dist[u]=value; L=0; get_array(u,-1);
sort(data+1,data+1+L);
int preans=0,l=1,r=L;
while (l<r)
{
if (data[l]+data[r]<=k) preans+=(r-l),l++; else r--;
}
return preans;
}
void solve(int u)
{
ans+=calc(u,0); vis[u]=1;
//cout<<"        ans       "<<u<<endl;
for (int p=now[u]; p; p=pre[p])
{
int vv=v[p];
//cout<<"                   "<<vv<<endl;
if (vis[vv]) continue;
ans-=calc(vv,val[p]); f[root=0]=n+1;
all=son[vv]; get_root(vv,-1);
solve(root);
}
}
int main()
{
n=read();
for (int i=1; i<=n-1; i++)
{
int u=read(),v=read(),value=read();
ins(u,v,value); ins(v,u,value);
}
k=read();
f[root=0]=n+1; all=n;
get_root(1,-1);
//cout<<"                "<<root<<endl;
solve(root);
printf("%d\n",ans);
return 0;
}


View Code

  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: