poj1741 Tree

终于不颓了今天

点分。对于无根树上的路径,对于一个点(视作根)来说,要么这条路径是经过当前点,要么是存在于这个点的子树,后者交给子树做,对于前者,处理出树中所有点到达根的距离,以及存在于根的那个孩子的子树。按距离排一遍序,从大到小枚举点,同时指针从小到大枚举和它配对的点,由于枚举点的大小单调递减,所以指针前面的点肯定可以和当前点配对,从当前指针位置枚举即可。这样就相当于O(n)的复杂度。还有,要用数组+时间戳记录当前某个子树的点在指针前有多少个,记录答案的时候要去掉同一子树的配对情况。

我TM的getrt完了之后为啥点分传的还是y

 

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;

int n,K;
struct node
{
    int x,y,d,next;
}a[21000];int len,last[11000];
void ins(int x,int y,int d)
{
    len++;
    a[len].x=x;a[len].y=y;a[len].d=d;
    a[len].next=last[x];last[x]=len;
}

int rt,sum,tot[11000],G[11000];
bool v[11000];
void getrt(int x,int fr)
{
    G[x]=0;tot[x]=1;
    for(int k=last[x];k;k=a[k].next)
    {
        int y=a[k].y;
        if(y!=fr&&v[y]==false)
        {
            getrt(y,x);
            G[x]=max(G[x],tot[y]);
            tot[x]+=tot[y];
        }
    }
    G[x]=max(G[x],sum-tot[x]);
    if(rt==0||G[rt]>G[x])rt=x;
}

//--------------------------

struct zz{int bel,d;}z[11000];int zlen;
bool cmp(zz z1,zz z2){return z1.d<z2.d;}
void getd(int x,int fr,int bel,int d)
{
    zlen++;
    z[zlen].bel=bel;z[zlen].d=d;
    for(int k=last[x];k;k=a[k].next)
    {
        int y=a[k].y;
        if(y!=fr&&v[y]==false)getd(y,x,bel,d+a[k].d);
    }
}
int ap[11000],tim,ti[11000];
int calc(int x)
{
    zlen=0;
    for(int k=last[x];k;k=a[k].next)
    {
        int y=a[k].y;
        if(v[y]==false)getd(y,x,y,a[k].d);
    }
    sort(z+1,z+zlen+1,cmp);
    
    int be=1,ret=0; tim++;
    for(int i=zlen;i>=1;i--)
    {
        if(z[i].d<=K)ret++;
        for(int j=be;j<i;j++)
        {
            if(z[i].d+z[j].d<=K)
            {
                if(ti[z[j].bel]!=tim){ti[z[j].bel]=tim;ap[z[j].bel]=0;}    
                ap[z[j].bel]++;
                be++;
            }
            else break;
        }
        if(i<be)ap[z[i].bel]--;
        ret+=min(i,be)-1-ap[z[i].bel];
    }
    return ret;
}

//---------------------------

int ans;
void divi(int x)
{
    v[x]=true;ans+=calc(x);
    for(int k=last[x];k;k=a[k].next)
    {
        int y=a[k].y;
        if(v[y]==false)
        {
            rt=0;sum=tot[y];
            getrt(y,x);
            divi(rt);
        }
    }
}


int main()
{
    freopen("1.in","r",stdin);
    freopen("1.out","w",stdout);
    while(scanf("%d%d",&n,&K)!=EOF)
    {
        if(n==0&&K==0)break;
        
        len=0;memset(last,0,sizeof(last));
        int x,y,d;
        for(int i=1;i<n;i++)
        {
            scanf("%d%d%d",&x,&y,&d);
            ins(x,y,d);ins(y,x,d);
        }
        rt=0;sum=n;
        memset(v,false,sizeof(v));
        getrt(1,0);
        
        ans=0;
        tim=0;memset(ti,0,sizeof(ti));
        divi(rt);
        printf("%d\n",ans);
    }
    return 0;
}

 

 

 

posted @ 2018-08-09 09:49  AKCqhzdy  阅读(118)  评论(0编辑  收藏  举报