1. 程式人生 > >【BZOJ3425】Poi2013 Polarization 猜結論+DP

【BZOJ3425】Poi2013 Polarization 猜結論+DP

lan sizeof sof 超過 ext 成了 double highlight 定向

【BZOJ3425】Poi2013 Polarization

Description

給定一棵樹,可以對每條邊定向成一個有向圖,這張有向圖的可達點對數為樹上有路徑從u到達v的點對(u,v)個數。求最小可達點對數和最大可達點對數

n<=250000

Sample Input

4
1 2
1 3
1 4

Sample Output

3 5

題解:想了一晚上,怎麽想怎麽是個搭建雙塔,結果看題解發現還真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