BZOJ

洛谷

最小可到达点对数自然是把一条路径上的边不断反向,也就是黑白染色后都由黑点指向白点。这样答案就是\(n-1\)。

最大可到达点对数,容易想到找一个点\(a\),然后将其子树分为两部分\(x,y\),\(x\)子树所有边全指向\(a\),\(a\)与\(y\)子树之间的边全指向\(y\)。这样答案就是\(sz[x]\times sz[y]\),要让\(sz[x],sz[y]\)尽量相等。找重心就好了。

然后DP,求划分重心两部分子树大小分别为\(x\)和\(n-1-x\)是否可行。

\(f[i]\)表示一部分子树\(sz\)和为\(i\)是否可行。转移就是个可行性背包,可以用\(bitset\)优化到\(\frac{n^2}{w}\),但还是不够。

对于\(size\geq\sqrt{n}\)的子树,最多不会超过\(\sqrt{n}\)个,可以直接背包转移。

对于\(size<\sqrt{n}\)的子树,根据\(size\)按多重背包做,可以直接二进制拆分。

复杂度为\(O(\frac{n\sqrt{n}\log n}{w})\)。

注意到\(\sum sz[i]=n\),所以\(sz[i]\)最多有\(O(\sqrt{n})\)种(\(1+2+...+\sqrt{n}\approx n\))。

即这是一个有\(O(\sqrt{n})\)个物品的多重背包。用二进制拆分有\(O(\sqrt{n}\log n)\)个物品。

二进制优化,从小到大,有一个物品\(x\)出现超过两次,就把两个合并成一个给\(2x\)。这样物品总数就是\(O(\sqrt{n})\)了。

所以复杂度为\(O(\frac{n\sqrt{n}}{w})\)。(虽然实际比上面的做法还慢一点儿==)

当根节点度数大于\(\sqrt{n}\)时可以用堆做:https://blog.csdn.net/neither_nor/article/details/52725690。大体看了看15年论文没看见这个做法 不细看了

//13704kb	3020ms(13572kb	3216ms)
#include <cmath>
#include <cstdio>
#include <cctype>
#include <bitset>
#include <algorithm>
#define gc() getchar()
typedef long long LL;
const int N=250005; int n,Enum,H[N],nxt[N<<1],to[N<<1],sz[N],root,Max,cnt[N];
std::bitset<N> f; inline int read()
{
int now=0;register char c=gc();
for(;!isdigit(c);c=gc());
for(;isdigit(c);now=now*10+c-'0',c=gc());
return now;
}
inline void AE(int u,int v)
{
to[++Enum]=v, nxt[Enum]=H[u], H[u]=Enum;
to[++Enum]=u, nxt[Enum]=H[v], H[v]=Enum;
}
void Get_root(int x,int f)
{
int mx=0; sz[x]=1;
for(int i=H[x],v; i; i=nxt[i])
if((v=to[i])!=f)
{
Get_root(v,x), sz[x]+=sz[v];
if(sz[v]>mx) mx=sz[v];
}
mx=std::max(mx,n-sz[x]);
if(mx<Max) Max=mx, root=x;
}
void DFS(int x,int f)
{
sz[x]=1;//重算一遍sz啊 想什么呢
for(int i=H[x],v; i; i=nxt[i])
if((v=to[i])!=f) DFS(v,x), sz[x]+=sz[v];
} int main()
{
n=read();
for(int i=1; i<n; ++i) AE(read(),read());
Max=1e9, Get_root(1,1), DFS(root,0); // f[0]=1;//O(n*sqrt(n)/w)
// for(int i=H[root]; i; i=nxt[i]) ++cnt[sz[to[i]]];
// for(int i=1; i<=n; ++i)
// if(cnt[i]>2) cnt[i<<1]+=(cnt[i]-1)>>1, cnt[i]=1+!(cnt[i]&1);
// for(int i=1; i<=n; ++i)
// while(cnt[i]--) f|=f<<i; f[0]=1; const int lim=sqrt(n);//O(n*sqrt(n)*logn/w)
for(int i=H[root]; i; i=nxt[i])
if(sz[to[i]]<lim) ++cnt[sz[to[i]]];
else f|=f<<sz[to[i]];
for(int i=1; i<lim; ++i)
for(int j=cnt[i],k=1; j; j-=k,k<<=1)
if(j>k) f|=f<<i*k;
else {f|=f<<i*j; break;} LL ans=0;
for(int i=1; i<n; ++i) if(f[i]) ans=std::max(ans,1ll*i*(n-1-i));
for(int i=1; i<=n; ++i) ans+=sz[i];
printf("%d %lld\n",n-1,ans-n); return 0;
}

BZOJ.3425.[POI2013]Polarization(DP 多重背包 二进制优化)的更多相关文章

  1. HDOJ(HDU).2844 Coins (DP 多重背包+二进制优化)

    HDOJ(HDU).2844 Coins (DP 多重背包+二进制优化) 题意分析 先把每种硬币按照二进制拆分好,然后做01背包即可.需要注意的是本题只需要求解可以凑出几种金钱的价格,而不需要输出种数 ...

  2. HDOJ(HDU).1059 Dividing(DP 多重背包+二进制优化)

    HDOJ(HDU).1059 Dividing(DP 多重背包+二进制优化) 题意分析 给出一系列的石头的数量,然后问石头能否被平分成为价值相等的2份.首先可以确定的是如果石头的价值总和为奇数的话,那 ...

  3. HDOJ(HDU).2191. 悼念512汶川大地震遇难同胞――珍惜现在,感恩生活 (DP 多重背包+二进制优化)

    HDOJ(HDU).2191. 悼念512汶川大地震遇难同胞――珍惜现在,感恩生活 (DP 多重背包+二进制优化) 题意分析 首先C表示测试数据的组数,然后给出经费的金额和大米的种类.接着是每袋大米的 ...

  4. hdu1059 dp(多重背包二进制优化)

    hdu1059 题意,现在有价值为1.2.3.4.5.6的石头若干块,块数已知,问能否将这些石头分成两堆,且两堆价值相等. 很显然,愚蠢的我一开始并想不到什么多重背包二进制优化```因为我连听都没有听 ...

  5. HDU 1171 Big Event in HDU 多重背包二进制优化

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1171 Big Event in HDU Time Limit: 10000/5000 MS (Jav ...

  6. hdu 2191 (多重背包+二进制优化)

    Problem Description 急!灾区的食物依然短缺!为了挽救灾区同胞的生命,心系灾区同胞的你准备自己采购一些粮食支援灾区,现在假设你一共有资金n元,而市场有m种大米,每种大米都是袋装产品, ...

  7. Coins(多重背包+二进制优化)

    Problem Description Whuacmers use coins.They have coins of value A1,A2,A3...An Silverland dollar. On ...

  8. Cash Machine POJ - 1276 多重背包二进制优化

    题意:多重背包模型  n种物品 每个m个  问背包容量下最多拿多少 这里要用二进制优化不然会超时 #include<iostream> #include<cstdio> #in ...

  9. HDU 5445 Food Problem(多重背包+二进制优化)

    http://acm.hdu.edu.cn/showproblem.php?pid=5445 题意:现在你要为运动会提供食物,总共需要提供P能量的食物,现在有n种食物,每种食物能提供 t 能量,体积为 ...

随机推荐

  1. 使用Idea初始化SpringMvc项目

    (1) (2) (3) (4) (5)感谢http://www.cnblogs.com/feiyujun/p/6537510.html (6)

  2. IAR拷贝工程后,修改工程名的方法

    在实际使用过程中,经常基于某个demo进行开发,但是demo的项目名往往不满足新项目的名称,如果重新建立工程,就需要进行一系列的配置,非常麻烦,其实可以直接修改项目名,做法如下; 1. 修改项目目录下 ...

  3. WebSphere的jython编码的一个坑

    was5.1版本,用"name=" in line这类判断字符串包含的方式时,系统会提示报错 TypeError: string member test needs char le ...

  4. oracle 数据库链路

    Oracle数据库链路的建立和使用 一.数据库链路的建立: 1.数据库链路的建立语法一般是:CREATE DATABASE LINK[db_link_name] CONNECT TO [user_na ...

  5. selenium自动化测试多条数据选择第一条

    如果我们测试时在一个页面中存在多条数据元素名称一致但是我们要选择第一条? 示意图: 方法一 driver.find_element_by_css_selector('.article-list/div ...

  6. 遍历集合的Iterator删除其中的元素

    package list; import java.util.LinkedList; /* * 遍历集合的时候删除其中的元素 从后往前删,每次都删除的是最后一个元素,不涉及移位 */public cl ...

  7. A. 【UR #17】滑稽树上滑稽果

    题解: 首先很显然的是这是一条链(特殊数据说是链是故意让人迷茫的??) 然后 自己就开始yy 觉得每一次是加入一个使得当前值最小的数 然而这tm又是特殊数据?? 那就写一波发现是错的 考虑一下特殊数据 ...

  8. Shell 错误输出重定向

    转自:https://www.cnblogs.com/vijayfly/p/6234575.html shell将标准错误输出重定向到 其他地方 经常可以在一些脚本,尤其是在crontab调用时发现如 ...

  9. 什么是AOP?

    AOP(Aspect-Oriented Programming,面向方面编程),可以说是OOP(Object-Oriented Programing,面向对象编程)的补充和完善.OOP引入封装.继承和 ...

  10. 《深入探索Androdi热修复技术原理(阿里巴巴)》--读书笔记

    No1: Hybrid就是原生和Html5混合开发app No2: 插件化方法Altas或者DroidPlugin No3: 热修复技术可以把更新补丁上传到云端,此时APP就可以直接从云端下拉补丁直接 ...