【BZOJ3425】Poi2013 Polarization 猜结论+DP
【BZOJ3425】Poi2013 Polarization
Description
给定一棵树,可以对每条边定向成一个有向图,这张有向图的可达点对数为树上有路径从u到达v的点对(u,v)个数。求最小可达点对数和最大可达点对数
n<=250000
Sample Input
1 2
1 3
1 4
Sample Output
题解:想了一晚上,怎么想怎么是个搭建双塔,结果看题解发现还真tm是搭建双塔。
本题的结论有点神,不过很好猜,证明见Claris博客。
第一问的答案一定是n-1,因为树是个二分图,所以我们将树黑白染色后所有边都从黑点指向白点即可。
第二问的答案是什么呢?我们猜测一定是先选中一个点,然后一半的边都指向这个点,另一半的边从这个点指出去。而选择哪个点呢?显然是重心啦。然后我们将重心之外所有联通块的大小都拿出来,这就变成了搭建双塔问题。
话说搭建双塔不是$O(n^2)$的吗?n=250000你逗我?然而正解很奇特。
当联通块大小<sqrt(n)时,我们将所有这样的联通块合到一起跑分组背包;当联通块大小>sqrt(n)时,这样的联通块不超过sqrt(n)个,所以暴力DP即可。DP时用bitset维护,于是时间复杂度就变成了神奇的$O({n \sqrt{n}\over 32})$。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <bitset>
#include <cmath>
using namespace std;
const int maxn=250010;
typedef long long ll;
int B,n,m,cnt,rt,mn;
ll sum,ans;
int to[maxn<<1],next[maxn<<1],head[maxn],siz[maxn],v[maxn],dep[maxn],s[maxn];
bitset<maxn> f;
inline int rd()
{
int ret=0,f=1; char gc=getchar();
while(gc<'0'||gc>'9') {if(gc=='-') f=-f; gc=getchar();}
while(gc>='0'&&gc<='9') ret=ret*10+(gc^'0'),gc=getchar();
return ret*f;
}
inline void add(int a,int b)
{
to[cnt]=b,next[cnt]=head[a],head[a]=cnt++;
}
void dfs(int x)
{
siz[x]=1,sum+=dep[x]-1;
int i,tmp=0;
for(i=head[x];i!=-1;i=next[i]) if(!dep[to[i]])
dep[to[i]]=dep[x]+1,dfs(to[i]),siz[x]+=siz[to[i]],tmp=max(tmp,siz[to[i]]);
tmp=max(tmp,n-siz[x]);
if(tmp<mn) mn=tmp,rt=x;
}
int main()
{
n=rd(),B=int(sqrt(double(n))),mn=1<<30;
memset(head,-1,sizeof(head));
int i,j,a,b;
for(i=1;i<n;i++) a=rd(),b=rd(),add(a,b),add(b,a);
dep[1]=1,dfs(1),memset(dep,0,sizeof(dep));
sum=0,dep[rt]=1,dfs(rt);
for(i=head[rt];i!=-1;i=next[i]) v[++m]=siz[to[i]];
f[0]=1;
for(i=1;i<=m;i++)
{
if(v[i]<=B) s[v[i]]++;
else f=f|(f<<v[i]);
}
for(i=1;i<=B;i++)
{
for(j=1;j<=s[i];s[i]-=j,j<<=1) f=f|(f<<(i*j));
if(s[i]) f=f|(f<<(i*s[i]));
}
for(i=0;i<=n;i++) if(f[i]) ans=max(ans,sum+(ll)i*(n-1-i));
printf("%d %lld",n-1,ans);
return 0;
}
【BZOJ3425】Poi2013 Polarization 猜结论+DP的更多相关文章
- BZOJ3425[POI2013]Polarization——DP+bitset+分块
题目描述 Everyone knew it would only be a matter of time. So what? Faced for years on, a peril becomes t ...
- BZOJ3425 : Poi2013 Polarization
最小值肯定是把树看作二分图,此时答案为$n-1$. 最大值一定是选取重心为根,任意一个子树要么全部指向根,要么全部背离根,这样可以制造最大的星型图. 统计出每个子树的大小后做01背包,如果小于$\sq ...
- 【CSP模拟赛】独立集(最长上升子序列&大力猜结论)
题目描述 有一天,一个名叫顺旺基的程序员从石头里诞生了.又有一天,他学会了冒泡排序和独 立集.在一个图里,独立集就是一个点集,满足任意两个点之间没有边.于是他就想把这两 个东西结合在一起.众所周知,独 ...
- D. Minimum Diameter Tree 思维+猜结论
D. Minimum Diameter Tree 思维+猜结论 题意 给出一颗树 和一个值v 把该值任意分配到任意边上 使得\(\sum\limits_{i,j}p_{ij}=v\) 使得 这颗树任意 ...
- hdu 5976 Detachment 脑洞题 猜结论
题目链接 题意 将\(x\)拆成\(a_1+a_2+...+\)的形式,且\(a_1\lt a_2\lt...\),使得\(a_1*a_2*...\)取到最大值 思路 大胆猜结论. 首先拆分的形式中肯 ...
- Atcoder Grand Contest 031 D - A Sequence of Permutations(置换+猜结论)
Atcoder 题面传送门 & 洛谷题面传送门 猜结论神题. 首先考虑探究题目中 \(f\) 函数的性质,\(f(p,q)_{p_i}=q_i\leftarrow f(p,q)\circ p= ...
- BZOJ.3425.[POI2013]Polarization(DP 多重背包 二进制优化)
BZOJ 洛谷 最小可到达点对数自然是把一条路径上的边不断反向,也就是黑白染色后都由黑点指向白点.这样答案就是\(n-1\). 最大可到达点对数,容易想到找一个点\(a\),然后将其子树分为两部分\( ...
- BZOJ 2222: [Cqoi2006]猜数游戏【神奇的做法,傻逼题,猜结论】
2222: [Cqoi2006]猜数游戏 Time Limit: 20 Sec Memory Limit: 259 MBSubmit: 604 Solved: 260[Submit][Status ...
- 51nod 1574 排列转换(猜结论)
分析 猜了一下结论,居然对了..........具体操作是:假设排列s是1,2,3,...,nk为排列p中最大的 没有放到正确位置的数,k的位置为posk的右边一定有一个数x<=pos(因为&l ...
随机推荐
- spring in action 7.2 小结
1 对于二进制文件上传功能的实现.在spring中使用multipart来处理,处理方式有两种. CommonsMultipartResolver:使用Jakarta Commons FileUplo ...
- unity, Root Motion
(引自:http://tieba.baidu.com/p/4323644080) 然后详细看了下这个文档:http://docs.unity3d.com/Manual/RootMotion.html ...
- PCI & PCIE Configuration Register Space
1.PCI-Compatible Configurationbits [1:0] are hard-wired, read-only and must return zeros when read.b ...
- java服务端json结果集传值给前端的数据输出格式
在服务端输出json数据时按照一定的格式输出时间字段,fastjson支持两种方式:1.使用JSON.toJSONStringWithDateFormat方法2.JSON.toJSONString方法 ...
- C#使用SendMessage传递字符串
来源:http://www.cnblogs.com/sizzle/archive/2007/08/29/874796.html 正文: 在C#中使用SendMessage,原本以为很简单的事,却处处碰 ...
- flume中Source
Spooling Directory Source: 以下2组参数解释: fileHeader及fileHeaderKey:fileHeader是个布尔值,可配置为true或者false,表示在flu ...
- Linux解决删除文件后空间没有释放问题_端口占用问题
使用命令 (1) losf | grep deleted 查询所有已经删除但是还未释放空间的进程,找到容量最大的线程,kill -9 pid 然后等待容量释放 (2) netstat -ano | g ...
- ubuntu下更改分辨率
在虚拟机中装了ubuntu但是没有1600*900的分辨率 第一步: xrandr -q 查看现在系统中所有的分辨率 第二步: cvt 1600 900 得到所需的更改分辨率数据 第三步: ww ...
- 打开palette面板
- dp - HNU 13404 The Imp
The Imp Problem's Link: http://acm.hnu.cn/online/?action=problem&type=show&id=13404&cour ...