• 点分治 poj1741


    题意:

    给出一颗树,询问有多少对点对距离<=k

    链接:

    http://poj.org/problem?id=1741

    题解:

    点分治的模板题

    点分治即采用分治思想分而治之

    考虑一颗子树内距离<=k的两种情况

    1.这两点连线不过根节点、

    那么就是这个问题的一个子问题

    2.这两点连线过根节点

    那么从根节点开始dfs出deep数组

    之后只需将deep数组排序,一个指针从head开始,一个指针从tail开始,只需满足dep[x]+dep[y]<=k即为满足的解

    但会发现如果两个节点位于同一颗子树中是不能构成的,所以应dfs减去这些答案

    **读入要优化

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<cmath>
    #include<ctime>
    #include<algorithm>
    using namespace std;
    #define maxn 110000 
    #define INF 98937894
    int root,n,m,c,dd,e,l,ans,sum,b[maxn],head[maxn],son[maxn],f[maxn],vis[maxn],deep[maxn],d[maxn];
    struct re{int a,b,c;}a[maxn*2];
    void arr(int x,int y,int z)
    {
        l++;
        a[l].a=head[x];
        a[l].b=y;
        a[l].c=z;
        head[x]=l;
    }
    void getroot(int x,int fa)
    {
        son[x]=1; f[x]=0;
        int u=head[x];
        while (u!=0)
        {
            int v=a[u].b;
            if (!(v==fa||vis[v]))
            {
              getroot(v,x);
              son[x]+=son[v];
              f[x]=max(f[x],son[v]);
          }
            u=a[u].a;
        }
        f[x]=max(f[x],sum-son[x]);
        if (f[x]<f[root]) root=x;
    }
    void getdeep(int x,int fa)
    {
        deep[++deep[0]]=d[x];
        int u=head[x];
        while (u!=0)
        {
            int v=a[u].b;
            if (!(v==fa||vis[v]))
            {
               d[v]=d[x]+a[u].c;
              getdeep(v,x);
          }
            u=a[u].a;
        }
    }
    int cal(int x,int v)
    {
        d[x]=v; deep[0]=0;
        getdeep(x,0);
        sort(deep+1,deep+deep[0]+1);
        int l=1,r=deep[0],sum=0;
        while (l<r)
        {
            if (deep[l]+deep[r]<=m) sum+=r-l,l++;
            else r--;
        }
        return sum;
    }
    void solve(int x)
    {
        ans+=cal(x,0);
        vis[x]=1;
        int u=head[x];
        while (u!=0)
        {
            int v=a[u].b;
            if (vis[v]!=1)
            { 
              ans-=cal(v,a[u].c);
              sum=son[v];
              root=0;
              getroot(v,x);
              solve(root);
          }
            u=a[u].a;
        }
    }
    int main()
    {
        freopen("noip.in","r",stdin);
        freopen("noip.out","w",stdout);
        std::ios::sync_with_stdio(false); 
        cin>>n>>m;
        while (n!=0)
        {
        memset(vis,0,sizeof(vis));
            memset(head,0,sizeof(head));
            l=ans=root=0;    f[0]=INF;
            for (int i=1;i<=n-1;i++)
            {
              cin>>c>>dd>>e,arr(c,dd,e),arr(dd,c,e);
            }
            sum=n;
            getroot(1,0); 
            solve(root);
            cout<<ans<<endl;
            cin>>n>>m;
        }
        return 0;
    }
    View Code
  • 相关阅读:
    Idea安装Scala插件(转)
    serialVersionUID的作用(转)
    [转]学习win10的bash使用ssh连接远程服务器
    [转]使用 Travis CI 部署你的 Hexo 博客
    【转】H5
    【转】Virtual DOM
    【转】hexo博客图片问题
    【转】V8 之旅: 垃圾回收器
    关于react-redux中Provider、connect的解析
    【转】webpack4
  • 原文地址:https://www.cnblogs.com/yinwuxiao/p/8179889.html
Copyright © 2020-2023  润新知