[51nod][cf468D]1558 树中的配对

Posted Swm_sxt

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[51nod][cf468D]1558 树中的配对相关的知识,希望对你有一定的参考价值。

http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1558

 

不是很懂dalao们用线段树是怎么写的……

反正找出重心以后每个子树一个堆,再来个全局堆就吼了

技术分享
#include<queue>
#include<stdio.h>
#include<algorithm>
#define MN 100001
using namespace std;

int read_p,read_ca;
inline int read(){
    read_p=0;read_ca=getchar();
    while(read_ca<0||read_ca>9) read_ca=getchar();
    while(read_ca>=0&&read_ca<=9) read_p=read_p*10+read_ca-48,read_ca=getchar();
    return read_p;
}
struct na{int y,z,ne;}b[MN<<1];
struct ma{int x,y;ma(int _x=0,int _y=0):x(_x),y(_y){}};
bool operator < (ma a,ma b){return a.x<b.x;}
priority_queue<ma> q[MN],Q,_q;
int n,m,l[MN],x,y,z,ro,mi=1e9,si[MN],nm=0,num=0,be[MN];
long long MMH;
inline void in(int x,int y,int z){b[++num].y=y;b[num].z=z;b[num].ne=l[x];l[x]=num;}
inline int min(int a,int b){return a<b?a:b;}
int dfs(int x,int f){
    int S=1,s,u=0;
    for (register int i=l[x];i;i=b[i].ne)
    if (b[i].y!=f){
        s=dfs(b[i].y,x);
        if (u<s) u=s;
        S+=s;
        MMH+=1LL*b[i].z*min(s,n-s);
    }
    if (n-S>u) u=n-S;
    if (u<mi) ro=x,mi=u;
    return S;
}
void DFS(int x,int f,int d){
    q[d].push(ma{-x,d});si[d]++;be[x]=d;
    for (register int i=l[x];i;i=b[i].ne)
    if (b[i].y!=f) DFS(b[i].y,x,d);
}
int work(int u){
    while (_q.top().x!=q[_q.top().y].top().x||q[_q.top().y].empty()) _q.pop();
    ma o;
    if (_q.top().y==u) o=_q.top(),_q.pop();
    while (_q.top().x!=q[_q.top().y].top().x||q[_q.top().y].empty()) _q.pop();
    u=_q.top().y;
    if (o.x) _q.push(o);
    return u;
}
int main(){
    register int i;
    n=read();
    if (n==1) return puts("0\n1"),0;
    for (i=1;i<n;i++) x=read(),y=read(),z=read(),in(x,y,z),in(y,x,z);
    dfs(1,0);
    q[0].push(ma{-ro,0});_q.push(ma{-ro,0});si[0]=1;
    for (i=l[ro];i;i=b[i].ne)
    DFS(b[i].y,ro,++nm),Q.push(ma{si[nm]<<1,nm}),_q.push(ma(q[nm].top().x,nm));
    printf("%lld\n",MMH<<1);
    for (i=1;i<=n;i++){
        while (Q.top().x!=si[Q.top().y]+q[Q.top().y].size()) Q.pop();
        if (be[i]==Q.top().y||Q.top().x<n-i+1) m=work(be[i]);else m=Q.top().y;
        if (i==ro&&-q[m].top().x>ro&&!q[0].empty()&&Q.top().x<n-i+1) m=0;
        printf("%d ",-q[m].top().x);
        q[m].pop();si[be[i]]--;if (!q[m].empty())_q.push(ma(q[m].top().x,m));
        Q.push(ma(si[m]+q[m].size(),m));Q.push(ma(si[be[i]]+q[be[i]].size(),be[i]));
    }
}
View Code

 

以上是关于[51nod][cf468D]1558 树中的配对的主要内容,如果未能解决你的问题,请参考以下文章

[CF468D] Tree

[51Nod] 配对

CF468D Tree(树的重心)

51nod 配对(求树的重心)

51Nod 1737 配对(树的重心)

51Nod 2006 飞行员配对(二分图最大匹配)