Luogu 4178 BZOJ1468 Tree Problem Solving Point and Conquer

An introductory exercise to divide and conquer.

topic link 

Link to BZOJ (authority question)

I will not repeat the idea of ​​dividing and conquering by points. Here I will focus on how to judge weights.

Let's look at the above picture, assuming that we remove 1 node and find d[2]=1, d[3]=d[4]=2

Suppose k is 5, so that we will consider the distance of nodes (2,3)(2,4)(3,4) to be less than k, and thus accumulate into the answer

But when we use 2 as the root to divide and conquer, we will also calculate (3,4) again, so it is repeated

So every time we calculate the answer, we need to subtract all the redundant cases, and the final answer is the answer we ask for

It is not difficult to find that the redundant situation is repeated in the root node and the root child node, we just subtract the answers of all the root child nodes when dividing and conquering

# include<iostream>
# include<cstdio>
# include<algorithm>
# include<set>
# include<cmath>
using namespace std;
const int mn = 40005;
struct edge{int to,next,dis;};
edge e[mn*2];
int head[mn],edge_max;
void add(int x,int y,int z)
{
    e[++edge_max].to=y;
    e[edge_max].dis=z;
    e[edge_max].next=head[x];
    head[x]=edge_max;
}
bool vis[mn];
int n,k,ans;
int mx[mn],siz[mn],root,sum;
int d[mn],deep[mn];
void getroot(int x,int fa)
{
    siz[x]=1,mx[x]=0;
    for(int i=head[x];i;i=e[i].next)
    {
        int u=e[i].to;
        if(u==fa || vis[u])
            continue;
        trotted (u, x);
        you [x] + = you [u];
        mx [x] = max (mx [x], siz [u]);
    }
    mx[x]=max(mx[x],sum-siz[x]);
    if(mx[root]>mx[x])
        root=x;
}
void getdeep(int x,int fa)
{
    deep[++deep[0]]=d[x];
    for(int i=head[x];i;i=e[i].next)
    {
        if(e[i].to==fa || vis[e[i].to])
            continue;
        d[e[i].to]=d[x]+e[i].dis;
        getdeep(e[i].to,x);
    }
}
int cal(int x,int now)
{
    d[x]=now,deep[0]=0;
    getdeep(x,0);
    sort(deep+1,deep+1+deep[0]);
    int t=0,l,r;
    for(int l=1,r=deep[0];l<r;)
    {
        if(deep[l]+deep[r]<=k)
        {
            t+=r-l;
            l++;
        }
        else r--;
    }
    return t;
}
void solve(int x)
{
    screw[x] = 1 ;
    ans+=cal(x,0);
    for(int i=head[x];i;i=e[i].next)
    {
          if(vis[e[i].to])
            continue;
          ans -= cal (e [i] .to, e [i] .dis);
          sum = siz [e [i] .to];
          root=0;
          getroot(e[i].to,root);
          solve(root);
    }
}
intmain ()
{
    int x,y,z;
    scanf("%d",&n);
    for(int i=1;i<n;i++)
    {
        scanf("%d%d%d",&x,&y,&z);
        add(x,y,z),add(y,x,z);
    }
    scanf("%d",&k);
    mx[0]=1<<30,sum=n;
    rooted( 1 , 0 );
    solve(root);
    printf("%d\n",ans);
    return 0;
}

 

 

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325631204&siteId=291194637