zoukankan      html  css  js  c++  java
  • beauty 树上贪心

      给定树上2k个点两两配对,求距离和最大值。1e6

      首先这种1e6的树上的题,一般都是$O(n)$的,所以两个思路,要么是DP,要么是贪心扫一遍。

      比如说这个题,首先就是对于每对点,我尽量把lca往上提,这样就能保证答案最大值,然后每往上抬一个,只要是边他的贡献就是1,所以我们可以dfs,策略是能往上抬就往上抬,带着一堆点伸出的边,如果能外边有足够配对的点,那就往上抬,如果没有,我就两两就地配对。

      然后就是比较帅气的AC了。

      

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int N=100010;
    int fr[N],fa[N],f[N],size[N],dep[N],a[N],b[N],p[N],n,k,s,tt,tot;
    long long ans;
    bool v[N];
    struct node{int to,pr;}mo[N*2];
    inline int rd()
    {
        int s=0,w=1;
        char cc=getchar();
        for(;cc<'0'||cc>'9';cc=getchar()) if(cc=='-') w=-1;
        for(;cc>='0'&&cc<='9';cc=getchar()) s=(s<<3)+(s<<1)+cc-'0';
        return s*w;
    }
    void add(int x,int y)
    {
        mo[++tt]=(node){y,fr[x]};
        fr[x]=tt;
    }
    void dfs(int x)
    {
        for(int i=fr[x];i;i=mo[i].pr)
        {
            int to=mo[i].to;
            if(to==fa[x])continue;
            fa[to]=x;
            dfs(to);
            f[x]+=f[to]+min(size[to],2*k-size[to]);
            size[x]+=size[to];
        }
        //cout<<x<<" "<<size[x]<<endl;
    }
    int main()
    {
        n=rd(),k=rd(),s=rd();
        for(int i=1;i<=k*2;i++) p[i]=rd(),size[p[i]]=1;
        for(int i=1;i<n;i++)
        {
            int x=rd(),y=rd();
            add(x,y);add(y,x);
        }
        dfs(1);
        printf("%d
    ",f[1]);
    }
    /*
    g++ 2.cpp -o 2 -O2
    ./2
    7 2 0
    1 5 6 2
    1 3
    3 2
    4 5
    3 7
    4 3
    4 6
    */
    View Code
  • 相关阅读:
    JavaScript事件处理
    JavaScript模拟"类"的三种方法
    非构造函数的继承和拷贝
    构造函数的继承
    vim开发环境
    socket之非阻塞
    网络编程
    多线程
    消息队列
    信号
  • 原文地址:https://www.cnblogs.com/starsing/p/11606843.html
Copyright © 2011-2022 走看看