您的位置:首页 > 其它

BZOJ1468 Tree

2015-06-03 15:28 309 查看
题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1468

一道水题,好久没有打点分治了有点手生。

犯了傻,打错了 addedge 调了1h。

基本思路就是按层分治,不超过 O(logn) 层,每一层 O(n) 或者 O(logn) 根据主定理 T(n) = T(n/2) + O(nlogn)

复杂度 O(nlog^2n) 。

此题在统计路径时还要注意容斥,要减去多余的路径。(具体看紫书即可)

#include <cstdio>
#include <cstring>
#include <algorithm>

#define N 50010
#define LL long long

using namespace std;

struct edge{
int x,to,v;
}E[N<<1];

int n,g
,K,totE,ansv;

inline void addedge(int x,int y,int v){
E[++totE]=(edge){y,g[x],v}; g[x]=totE;
E[++totE]=(edge){x,g[y],v}; g[y]=totE;
}

#define p E[i].x

namespace Tree_Dc{
int siz
,root,f
,totn,a
,d
,tot;
bool v
;

void Find_Hea(int x,int ft){
siz[x]=1; f[x]=0;
for(int i=g[x];i;i=E[i].to)
if(ft!=p&&!v[p]){
Find_Hea(p,x);
siz[x]+=siz[p];
f[x]=max(f[x],siz[p]);
}
f[x]=max(f[x],totn-siz[x]);
if(!root||f[x]<f[root])
root=x;
}

inline int Root(int x){
root=0; totn=siz[x];
Find_Hea(x,x);
return root;
}

void dfs(int x,int ft){
a[++tot]=d[x];
for(int i=g[x];i;i=E[i].to)
if(!v[p]&&p!=ft){
d[p]=d[x]+E[i].v;
dfs(p,x);
}
}

inline int count_path(int x,int v){
d[x]=v; tot=0;
dfs(x,0);
sort(a+1,a+tot+1);
int ans=0,tmp=1;
for(int i=2;i<=tot;i++){
while(tmp<i&&a[i]+a[tmp+1]<=K) tmp++;
while(tmp&&a[i]+a[tmp]>K) tmp--;
ans+=min(tmp,i-1);
}
return ans;
}

void DC(int x){
int tmp=ansv;
ansv+=count_path(x,0);
v[x]=1;
for(int i=g[x];i;i=E[i].to)
if(!v[p]){
ansv-=count_path(p,E[i].v);
DC(Root(p));
}
}
}

int main(){
freopen("test.in","r",stdin);
scanf("%d",&n);
for(int i=1,x,y,v;i<n;i++){
scanf("%d%d%d",&x,&y,&v);
addedge(x,y,v);
}
scanf("%d",&K);
Tree_Dc::siz[1]=n;
Tree_Dc::DC(Tree_Dc::Root(1));
printf("%d\n",ansv);
return 0;
}


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