bzoj 3425: Poi2013 Polarization

Description

 

Everyone knew it would only be a matter of time. So what? Faced for years on, a peril becomes the every-day reality. It loses its meaning...

Today the letter of the Bitotian char Bittard to the Byteotian king Byteasar was released to the public. Bitotia requested annexation of the whole Byteotia on pain of using the Bit Polarizing Magnet (BPM). If used, the BPM would make each and every road in Byteotia unidirectional. The enemy knows only too well that this could be a fatal blow to the minimalist Byteotian infrastructure - there is a unique way between each pair of towns.

How badly can the BPM damage the Byteotian infrastructure? Determine the minimum and the maximum number of such pairs of towns that it will still be possible to travel from one of them to the other while observing the new roads orientation.

给定一棵树,可以对每条边定向成一个有向图,这张有向图的可达点对数为树上有路径从u到达v的点对(u,v)个数。求最小可达点对数和最大可达点对数

 

 

 

Input

The first line of the standard input gives a single integer N (1<=N<=250000), the number of towns in Byteotia. The N-1 lines that follow describe these roads. Each such line holds two integers, U  and V (1<=U<=V<=N) , which indicate that there is a direct road (still bidirectional at the moment) linking the towns no.  and .

 


 

Output

 

Two integers should be printed to the first and only line of the standard output. The first number should be the minimum and the second - the maximum number of pairs of towns which could remain connected (though in one direction only) after the roads are polarized.

 


 

Sample Input

4
1 2
1 3
1 4

Sample Output


3 5

 

最小答案一定是n−1,只要按边深度的奇偶性取不同的方向就可以取到了。

最大答案存在一个结论,就是以重心为根,剩下每棵子树要么全部指向根,要么全部背离根。假设指向根的子树大小之和是x,那么背离根的子树大小之和就是n−x−1,所有穿过根的贡献就是x(n−x−1)。

所以现在要做的就是拿重心的所有儿子出来做一个01背包看可以组成哪些x。直接背包压位的话复杂度是$O(\frac{n^2}{32})$,然后把$ \geq \sqrt{n} $  的暴力做, 把$ \leq \sqrt{n} $  的放在一起二进制分组做,复杂度就是$O(\frac{n\sqrt{n}}{32})$。

 

 1 #include<bits/stdc++.h>
 2 using namespace std;  
 3 #define ll long long 
 4 int const N=250000+10;  
 5 struct node{
 6     int to,nt;  
 7 }e[N<<1];  
 8 int sz[N],son[N],h[N],cnt,n,rt,num[501]; 
 9 ll f[N];   
10 bitset<N> g;     
11 void add(int a,int b){
12     e[++cnt].to=b;  
13     e[cnt].nt=h[a];  
14     h[a]=cnt;  
15 }   
16 void dfs(int x,int fa){
17     sz[x]=1;   
18     f[x]=0; 
19     for(int i=h[x];i;i=e[i].nt){
20         int v=e[i].to;  
21         if(v==fa) continue;  
22         dfs(v,x);  
23         sz[x]+=sz[v];  
24         f[x]+=f[v]+sz[v];  
25         if(sz[son[x]]<sz[v]) 
26             son[x]=v;  
27     }  
28     int t=max(n-sz[x],sz[son[x]]);  
29     if(t<=n/2) rt=x;   
30 }  
31 
32 int main(){    
33     scanf("%d",&n); 
34     for(int i=1;i<n;i++){
35         int x,y;  
36         scanf("%d%d",&x,&y);  
37         add(x,y);  
38         add(y,x);  
39     }
40     dfs(1,0);  
41     dfs(rt,0);    
42     g[0]=1;  
43     for(int i=h[rt];i;i=e[i].nt){
44         int v=e[i].to;  
45         if(sz[v]>500) 
46             g|=g<<sz[v]; 
47         else  num[sz[v]]++;     
48     }   
49     int j,k;   
50     for(int i=1;i<=500;i++)  
51         for(j=num[i],k=1; j;j-=k,k=min(j,k<<1))  
52             g|=g<<i*k;  
53     for(int i=n/2;i>=0;i--)  
54         if(g[i]){
55             printf("%d %lld\n",n-1,f[rt]+1LL*i*(n-i-1));  
56             break;  
57         }  
58     return 0; 
59 } 
View Code

 

posted @ 2019-07-25 01:47  zjxxcn  阅读(177)  评论(0编辑  收藏  举报