poj1741 Tree

来源:互联网 发布:2017年大学生就业数据 编辑:程序博客网 时间:2024/05/21 06:24

一万年不打点分治的我来打点分治了。。。(╯‵□′)╯︵┻━┻
重新复(学)习了一波点分治,之前学的不是很懂。。然后现在发现这东西相当简单= =至少比链剖简单多了,好吧其实都差不多简单。。。
点分治的话,就是讨论对于一个点,答案的两种情况,即是否跨过这个点,不跨过的我们可以直接算他的子树,跨过的我们可以可以对这个点延伸出的几棵子树各做一次dfs
记录子树中出现的距离值,对于一棵树的距离值数组,排序以后求出ans1,然后对于他的子树,求出ans2,ans1-ans2就是总答案,因为会有两个点都在子树内的被算重。。

#include<cstdio>#include<algorithm>#include<cstring>#include<iostream>#define fo(i,a,b) for(int i=a;i<=b;i++)#define fd(i,a,b) for(int i=a;i>=b;i--)using namespace std;const int N=1e5+5;const int inf=1e9;int f[N];int n,k,cnt,sum,ans,root;int head[N],dep[N],d[N],son[N];bool vis[N];int go[N],next[N],val[N],tot;inline int read(){    int x=0,f=1;char ch=getchar();    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}    return x*f;}inline void add(int x,int y,int z){    go[++tot]=y;    val[tot]=z;    next[tot]=head[x];    head[x]=tot;}inline void getroot(int x,int fa){    son[x]=1;    f[x]=0;    for(int i=head[x];i;i=next[i])    {        int v=go[i];        if (vis[v]||v==fa)continue;        getroot(v,x);        son[x]+=son[v];        f[x]=max(f[x],son[v]);    }    f[x]=max(f[x],sum-son[x]);    if (f[x]<f[root])root=x;}int tim=0;inline void getdep(int x,int fa){    dep[++dep[0]]=d[x];    for(int i=head[x];i;i=next[i])    {        int v=go[i];        if (v==fa||vis[v])continue;        d[v]=d[x]+val[i];        getdep(v,x);    }}inline int cal(int x,int now){    d[x]=now,dep[0]=0;    getdep(x,0);    sort(dep+1,dep+dep[0]+1);    int t=0,l,r;    l=1,r=dep[0];    while (l<r)    {        if (dep[l]+dep[r]<=k)        {            t+=r-l;            l++;        }        else r--;    }    return t;}inline void work(int x){    ans+=cal(x,0);    vis[x]=1;    for(int i=head[x];i;i=next[i])    {        int v=go[i];        if (vis[v])continue;        ans-=cal(v,val[i]);        sum=son[v];        root=0;        getroot(v,root);        work(root);    }}int main(){    while (1)    {        ans=0;        root=0,tot=0;        memset(vis,0,sizeof(vis));        memset(head,0,sizeof(head));        n=read(),k=read();        if (!n)break;        fo(i,1,n-1)        {            int x=read(),y=read(),z=read();            add(x,y,z);            add(y,x,z);         }        sum=n;        f[0]=inf;        getroot(1,0);        work(root);        printf("%d\n",ans);    }    return 0;}
0 0
原创粉丝点击