zoukankan      html  css  js  c++  java
  • 题解 洛谷 P3563 【[POI2013]POL-Polarization】

    先考虑最小值,因为树是二分图,所以可以进行黑白染色,将其分成左右部图,让左部图向右部图连边即可构造最小值,为 (n-1)

    对于最大值,最优情况一定是以一个点为中心,其各个子树内边的状态为要么该点能到达子树内的每个点,即外向,要么子树内的每个点能到达该点,即内向,且该点为树的重心。

    可以简单的进行证明。考虑边的状态让这棵树有了两个上面描述的中心,两个中心之间的路径上一半的边指向第一个中心,一半的边指向第二个中心。发现若这条路径边的方向只指向一个中心,答案会更优,所以就将这两个中心合并为一个,同理,若存在多个中心,合并为一个会更优。因为中心的各个子树的外向个数和内向个数会乘起来贡献给答案,所以中心选取树的重心可以更好的分配外向内向的子树大小。

    考虑将中心的各个子树分为外向和内向两个集合,两个集合大小越接近 (frac{n}{2}) 越优。可以通过二进制拆分来优化这个多重背包问题,因为只用考虑存在性,所以也采用 (bitset) 来优化。

    (code:)

    #include<bits/stdc++.h>
    #define maxn 500010
    using namespace std;
    typedef long long ll;
    template<typename T> inline void read(T &x)
    {
        x=0;char c=getchar();bool flag=false;
        while(!isdigit(c)){if(c=='-')flag=true;c=getchar();}
        while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
        if(flag)x=-x;
    }
    int n,root;
    ll ans;
    int siz[maxn],ma[maxn],cnt[maxn];
    bitset<maxn> s;
    struct edge
    {
        int to,nxt;
    }e[maxn];
    int head[maxn],edge_cnt;
    void add(int from,int to)
    {
        e[++edge_cnt]=(edge){to,head[from]};
        head[from]=edge_cnt;
    }
    void dfs(int x,int fa)
    {
        siz[x]=1;
        for(int i=head[x];i;i=e[i].nxt)
        {
            int y=e[i].to;
            if(y==fa) continue;
            dfs(y,x),siz[x]+=siz[y];
            ma[x]=max(ma[x],siz[y]);
        }
        ma[x]=max(ma[x],n-siz[x]);
        if(ma[x]<ma[root]) root=x;
    }
    int main()
    {
        read(n),ma[0]=n;
        for(int i=1;i<n;++i)
        {
            int x,y;
            read(x),read(y);
            add(x,y),add(y,x);
        }
        dfs(1,0),dfs(root,0);
        for(int i=1;i<=n;++i) ans+=siz[i]-1;
        for(int i=head[root];i;i=e[i].nxt) cnt[siz[e[i].to]]++;
        for(int i=1;i<=n;++i)
            while(cnt[i]>2)
                cnt[i]-=2,cnt[i*2]++;
        s[0]=1;
        for(int i=1;i<=n;++i)
            for(int j=1;j<=cnt[i];++j)
                s|=s<<i;
        for(int i=n/2;i;--i)
        {
            if(!s[i]) continue;
            printf("%d %lld
    ",n-1,ans+(ll)i*(n-i-1));
            break;
        }
        return 0;
    }
    
  • 相关阅读:
    2019 NJCTF WarmUp
    家用路由器渗透过程总结
    IOT 安全资料整合(主要是路由器)
    由一道工控路由器固件逆向题目看命令执行漏洞
    路由器漏洞挖掘之 DIR-850/645 命令执行漏洞复现
    路由器漏洞挖掘之 DIR-815 栈溢出漏洞分析
    从外网到内网的渗透姿势分享
    ESP8266 显示实时天气信息
    静态链接学习之 ELF 文件 DIY
    ROP-Tamu CTF 2018-pwn5
  • 原文地址:https://www.cnblogs.com/lhm-/p/13399231.html
Copyright © 2011-2022 走看看