[POI2013]POL-Polarization

题目描述

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.

给定一颗树,请给树边改成有向边,求连通的点对个数的最大最小值。点对连通,要么a能到达b,要么b能到达a。(n<=250000)

输入输出格式

输入格式:

The first line of the standard input gives a single integer (), the number of towns in Byteotia.

The lines that follow describe these roads.

Each such line holds two integers, and (), which indicate that there is a direct road (still bidirectional at the moment) linking the towns no. and .

In tests worth 60% of the total points, the additional constraint holds;moreover, in some of those, worth 30% of the total points, it even holds that .

输出格式:

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.

输入输出样例

输入样例#1:

4
1 2
1 3
1 4

输出样例#1:

3 5

说明

给定一颗树,请给树边改成有向边,求连通的点对个数的最大最小值。点对连通,要么a能到达b,要么b能到达a。(n<=250000)


神奇的一道题反正我不会

首先考虑最小值

因为每连出去一条边至少会形成一个点对

所以我们就考虑最小的情况

因为是一颗树

所以只有n-1条边,答案就是n-1

具体连法就是第i-1层向第i层连的边与第i层向第i+1层的连的边的方向相反

然后考虑最大值怎么求反正我不会证明

最大值就是找打树的重心

然后每个子树内部连边方向要相同

然后尽量使得连向root的边的子树大小之和和root向外连出的边的子树大小之和相差小

就感性理解一下反正我也不会证明

然后把每个子树按照大小二进制拆分一下

之后做一个背包就行了

#include<queue>
#include<bitset>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
# define LL long long
const int M = 250005 ;
const int INF = 2147483647 ;
using namespace std ;
inline int read() {
    char c = getchar() ; int x = 0 , w = 1 ;
    while(c>'9'||c<'0') { if(c=='-') w = -1 ; c = getchar() ; }
    while(c>='0'&&c<='9') { x = x*10+c-'0' ; c = getchar() ; }
    return x*w ;
}

int n , m ;
struct E { int Nxt , to ; }edge[M<<1];
int hea[M] , num ;
inline void add_edge(int from , int to) {
    edge[++num].Nxt = hea[from] ; edge[num].to = to ; hea[from] = num ;
}
int size[M] , tmax , root , dep[M] , w[M<<1] ;
LL Ans = 0 ;
bitset< M > f ;
void Getroot(int u , int father) {
    size[u] = 1 ; int Maxson = 0 ;
    for(int i = hea[u] ; i ; i = edge[i].Nxt) {
        int v = edge[i].to ;
        if(v == father) continue ;
        Getroot(v , u) ;
        size[u] += size[v] ; 
        Maxson = max(Maxson , size[v]) ;
    }
    Maxson = max(Maxson , n - size[u]) ;
    if(Maxson < tmax)  
        tmax = Maxson , root = u ;
}
int main() {
    n = read() ;
    for(int i = 1 , u , v ; i < n ; i ++) {
        u = read() , v = read() ;
        add_edge(u , v) ; add_edge(v , u) ;
    }
    tmax = n ;
    Getroot(1 , 0) ;
    Getroot(root , root) ;
    for(int i = 1 ; i <= n ; i ++) Ans += size[i] - 1 ;
    for(int i = hea[root] ; i ; i = edge[i].Nxt) {
        int v = edge[i].to ;
        ++w[size[v]] ;
    }
    for(int i = 1 ; i <= n ; i ++)
        while(w[i] > 2) 
		    w[i] -= 2 , ++w[i<<1] ;
    f[0] = 1 ;
    for(int i = 1 ; i <= n ; i ++)
        while(w[i] -- )
            f |= f << i ;
    int x ;
    for(x = (n >> 1) ; !f[x] ; -- x) ;
    printf("%d %lld
",n - 1 , Ans + 1LL * x * (n - 1 - x)) ; 
    return 0 ;
}
原文地址:https://www.cnblogs.com/beretty/p/9594944.html