[hdu6567]Cotree

Time Limit: 2000/1000 MS (Java/Others)
Memory Limit: 262144/262144 K (Java/Others)

分数:2500
Problem Description
Avin has two trees which are not connected. He asks you to add an edge between them to make them connected while minimizing the function i = 1 n j = i + 1 n d i s ( i , j ) ∑^n_{i=1}∑^n_{j=i+1}dis(i,j) , where d i s ( i , j ) dis(i,j) represents the number of edges of the path from i i to j j . He is happy with only the function value.

Input
The first line contains a number n ( 2 < = n < = 100000 ) n(2<=n<=100000) . In each of the following n 2 n−2 lines, there are two numbers u u and v v , meaning that there is an edge between u u and v v . The input is guaranteed to contain exactly two trees.

Output
Just print the minimum function value.

Sample Input

3
1 2

Sample Output

4

题意:
给定一棵树的 n 2 n-2 条边,让你加上一条边,让他变为一棵树,并且满足 i = 1 n j = i + 1 n d i s ( i , j ) ∑^n_{i=1}∑^n_{j=i+1}dis(i,j) 最小, d i s ( i , j ) dis(i,j) i i j j 的距离。
题解:
首先我们对两个树进行dp,对每个节点计算 g [ x ] g[x] ,表示为以 x x 为根节点
的子树中所有节点到根节点的距离之和。
然后我们再dfs一次计算对于一个节点来说,同一个树的其他所有点到这个点的距离之和 p [ i ] p[i]
那么 ( p [ i ] ) / 2 (\sum p[i])/2 是不加边之前的答案。那么加边之后的答案,只需要找到两个数各自最小的两个 p [ i ] p[i] ,设为 a 1 a1 , a 2 a2 ,答案就是 ( a 1 + c 1 ) c 2 + a 2 c 1 (a1+c1)*c2+a2*c1

#include<bits/stdc++.h>
#define ll long long
using namespace std;
int n;
vector<int>G[200004];
int bl[200004],sz[200004];
ll g[200004],ans[4],res;
int c[4],rt[4];
void dfs(int x,int bt){
    bl[x]=bt;
    ++c[bt];
    sz[x]=1;g[x]=0;
    for(int i=0;i<G[x].size();i++){
        int to=G[x][i];
        if(bl[to])continue;
        dfs(to,bt);
        sz[x]+=sz[to];
        g[x]+=sz[to];
        g[x]+=g[to];
    }
}
void dfs2(int x,int fa,ll val){
    res+=val+g[x];
    //cout<<x<<" "<<val+g[x]<<" "<<bl[x]<<" || "<<endl;
    if(ans[bl[x]]==-1||(ans[bl[x]]!=-1&&ans[bl[x]]>val+g[x])){
        ans[bl[x]]=val+g[x];
    }
    for(int i=0;i<G[x].size();i++){
        int to=G[x][i];
        if(to==fa)continue;
        dfs2(to,x,val+c[bl[x]]-2*sz[to]+g[x]-g[to]);
    }
}
int w33ha(){
    res=0;
    for(int i=1;i<=n;i++){
        G[i].clear();
        g[i]=0;
        ans[i]=0;
        bl[i]=0;
    }
    c[1]=0;c[2]=0;
    rt[1]=0;rt[2]=0;
    ans[1]=-1;ans[2]=-1;
    for(int i=1;i<=n-2;i++){
        int u,v;scanf("%d%d",&u,&v);
        G[u].push_back(v);
        G[v].push_back(u);
    }
    int blo=0;
    for(int i=1;i<=n;i++){
        if(!bl[i]){
            dfs(i,++blo);
            rt[blo]=i;
        }
    }
    //for(int i=1;i<=n;i++)cout<<g[i]<<" ";cout<<endl;
    for(int i=1;i<=blo;i++){
        dfs2(rt[i],0,0);
    }
    //for(int i=1;i<=n;i++)cout<<bl[i]<<" ";cout<<endl;
    res>>=1;
    //cout<<res<<endl;
    //cout<<" "<<ans[1]<<" "<<ans[2]<<endl;
    printf("%lld\n",res+(ans[1]+c[1])*(c[2])+(ans[2]*c[1]));
    return 0;
}
int main(){
    while(scanf("%d",&n)!=EOF)w33ha();
    return 0;
}
发布了302 篇原创文章 · 获赞 19 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/dxyinme/article/details/99172555
hdu
今日推荐