https://vjudge.net/contest/161666

难点都在于如何处理出答案已经减掉重复的。

POJ - 1741

题意:给一个树,路径带权,问两个点距离小于等于给定数k有多少对。

点分治的基础题,算答案的时候因为是单调的所以两头走,

#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
#define rep(i,l,r) for(int i=l;i<=r;i++)
#define dow(i,l,r) for(int i=r;i>=l;i--)
#define repedge(i,x) for(int i=fi[x];i;i=e[i].next)
#define maxn 20020
#define maxm 200010
using namespace std;

typedef struct {
    int v,next,toward;
}E;
E e[maxm];
int d[maxn],fi[maxn],size[maxn],msize[maxn],vis[maxn],n,tot,total,m,ans;

void addedge(int j,int k,int l)
{
    e[++total].toward=k;
    e[total].next=fi[j];
    fi[j]=total;
    e[total].v=l;
}

void dfs_len(int x,int fa,int len)
{
    d[++tot]=len;
    repedge(i,x) {
        int too=e[i].toward;
        if (!vis[too] && too!=fa) 
            dfs_len(too,x,len+e[i].v);
    }
}

void dfs_size(int x,int fa)
{
    size[x]=1;
    repedge(i,x) {
        int too=e[i].toward;
        if (!vis[too] && too!=fa) {
            dfs_size(too,x);
            size[x]+=size[too];
        }
    }
}

int dfs_root(int x,int fa,int y)
{
    int r1=0;
    msize[x]=y-size[x];
    repedge(i,x) {
        int too=e[i].toward;
        if (!vis[too] && too!=fa) {
            msize[x]=max(msize[x],size[too]);
            int r2=dfs_root(too,x,y);
            if (!r1 || msize[r2]<msize[r1]) r1=r2;
        }
    }
    if (!r1 || msize[r1]>msize[x]) r1=x;
    return r1;
}

int more(int x,int len)
{
    tot=0;
    dfs_len(x,0,len);
    sort(d+1,d+1+tot);
    int l=0,r=tot,sum=0;
    while (++l<r) {
        while (d[l]+d[r]>m && l<r) r--;
        sum+=r-l;
    }
    return sum;
}

void calc(int x)
{
    int root;
    dfs_size(x,0);
    root=dfs_root(x,0,size[x]);
    ans+=more(root,0);
    vis[root]=1;
    repedge(i,root) {
        int too=e[i].toward;
        if (!vis[too]) {
            ans-=more(too,e[i].v);
            calc(too);
        }
    }
}

int main()
{
    while (~scanf("%d %d",&n,&m)) {
        if (!n) break; 
        memset(vis,0,sizeof(vis));
        memset(fi,0,sizeof(fi));
        total=0;
        rep(i,1,n-1) {
            int j,k,l;
            scanf("%d %d %d",&j,&k,&l);
            addedge(j,k,l);
            addedge(k,j,l);
        }
        ans=0;
        calc(1);
        printf("%d\n",ans);
    }
    return 0;
}
View Code

相关文章:

  • 2021-05-10
  • 2021-05-31
  • 2022-12-23
  • 2021-05-30
  • 2022-12-23
  • 2021-06-21
  • 2021-12-30
猜你喜欢
  • 2021-12-30
  • 2021-08-31
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2021-11-07
  • 2021-07-12
相关资源
相似解决方案