HDU6567(树重心模板练习题)

传送门

题意:给你两棵树,让你把这两颗树连接起来,要求连接起来的树的任意两个节点的距离最小
题解:树重心模板训练题,找到这两颗树的树重心,然后连接,最后求一次,树中所有路径的长度。
PS:因为没颗树的节点数是不清楚的,只有找到树的节点数才能DP找到树重心,所以要在重心之前DFS一遍找树大小,这里也可用并查集来实现。笔者在这里WA了10发。。。。
PS2:AC-CODE 所用到的板子传送门

AC-CODE

#include  
using namespace std;
const int mx =  2000000+7;
typedef long long ll;
typedef unsigned  long long ull;
vector<ll> ve[mx];
int f[mx]={0};
ll d[mx]={0},e[mx]={0},n;
ll minnode =0,minnoden=1e18+7;
ll sum = 0;
ll ans=0;
void ddd(int u,int fa){
    f[u] = 1;
    sum++;
    d[u] = 1;
    int son = ve[u].size(); //msub是节点为u的最大子树的节点个数
    for(int i=0;i<son;i++) {
        int v=ve[u][i];
        if(v==fa) continue;
        ddd(v,u);
        d[u]+=d[v];
    }
}
void dfs(int u,int fa,int s){
    d[u] = 1; //节点本身
    ll masub = 0;
    int son = ve[u].size(); //msub是节点为u的最大子树的节点个数
    for(int i=0;i<son;i++) {
        int k = ve[u][i];
        if (k!=fa) {
            dfs(k,u,s);
            d[u] += d[k];
            masub = max(masub,d[k]);
        }
    }
    masub = max(masub,s-d[u]);   //主要用来防止一条链的情况,看看父亲的情况
    if (minnoden>masub){
        minnode = u;
        minnoden = masub;
    }
}
void ansdfs(int rt,int fa){
    e[rt]=1;
    int son = ve[rt].size();
    for(int i=0;i<son;i++){
        int k = ve[rt][i];
        if(k!=fa){
            ansdfs(k,rt);
            e[rt]+= e[k];
        }
    }
    ans += e[rt]*(n-e[rt]);
}
int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
#ifdef ACM_LOCAL
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
#endif
    cin >> n;
    for (int i = 1; i <= n - 2; i++) {
        ll u, v;
        cin >> u >> v;
        ve[u].push_back(v);
        ve[v].push_back(u);
    }
    ddd(1,0);
    memset(d, 0, sizeof(d));
    ll s = sum;
    minnode = 0, minnoden = 1e18+7;
    dfs(1, 0,s);
    int root1 = minnode;

    minnode = 0, minnoden = 1e18+7;
    memset(d, 0, sizeof(d));
    int r = 2;
    for(int i=1;i<=n;i++){
        if (f[i]==0) {
            r = i;
            break;
        }
    }
    dfs(r,0,n-s);
    int root2 = minnode;
    ve[root1].push_back(root2);
    ve[root2].push_back(root1);

    ansdfs(1,0);
    cout<<ans<<endl;
    return 0;
}

你可能感兴趣的:(树的重心)