zoukankan      html  css  js  c++  java
  • CF 468D

    Description


     
     

    Input

    Output

     

    Sample Input

    输入1:
    2
    1 2 3
    输入2:
    5
    1 2 2
    1 3 3
    2 4 4
    2 5 5

    Sample Output

    输出1:
    6
    2 1
    输出2:
    32
    2 1 4 5 3
     

    Data Constraint

     
    首先Ans=dep[i]+dep[p[i]]-2*dep[lca(i,p[i])];
    易证当根为重心时Ans取最小值,我们只需要求字典序最小。
    接下来就是一个二分图匹配的问题,首先我们贪心的选择。但在某些时候我们不能这样选,当一棵子树未匹配数过多时(即到以后只能自己匹配自己时)我们要优先匹配该树中的点。
    那么什么时候是过多呢╮(╯▽╰)╭
    我们设L[i]为i子树左边未匹配的点数,R[i]为右边未匹配的点数。
    那么当L[i]>Rsum-R[i]时会出现过多的情况,
    两边同时加上R[i]变为L[i]+R[i]>Rsum
    我们只需用一棵线段树记录L[i]+R[i]看是否出现以上情况即可
     
    #include<cstdio>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #include<queue>
    using namespace std;
    typedef long long ll;
    
    priority_queue<int> H[100011];
    
    struct Tree{
        int mn,mx,id;
    }tr[600011];
    
    Tree emp;
    int bel[100011],g[100011],next[200022],y[200022],que[100011],len[200011];
    ll dis[100011];
    int mx[100011],size[100011],fa[100011],ans[100011],sz[100011];
    ll Ans;
    int n,i,x,z,q,root,tot,tt;
    
    void star(int i,int j,int k)
    {
        tt++;
        next[tt]=g[i];
        g[i]=tt;
        y[tt]=j;
        len[tt]=k;
    }
    
    void Bfs(int st)
    {
        int l,r,x,j,k;
        memset(size,0,sizeof(size));
        memset(dis,0,sizeof(dis));
        memset(fa,0,sizeof(fa));
        l=r=1;
        que[l]=st;
        while(l<=r){
            x=que[l];
            j=g[x];
            while(j!=0){
                k=y[j];
                if(k!=fa[x]){
                    fa[k]=x;
                    r++;
                    que[r]=k;
                    dis[k]=dis[x]+len[j];
                }
                j=next[j];
            }
            l++;
        }
        for(i=n;i>=1;i--){
            x=que[i];
            size[x]++;
            mx[x]=max(mx[x],n-size[x]);
            if(mx[x]<=n/2)root=x;
            size[fa[x]]+=size[x];
            mx[fa[x]]=max(mx[fa[x]],size[x]);
        }
    }
    
    void dfs(int x)
    {
        int j,k;
        bel[x]=tot;
        sz[tot]++;
        H[tot].push(-x);
        j=g[x];
        while(j!=0){
            k=y[j];
            if(k!=fa[x])dfs(k);
            j=next[j];
        }
    }
    
    void Prepare()
    {
        int j,k;
        bel[root]=1;
        H[1].push(-root);
        tot=1;
        sz[1]=1;
        j=g[root];
        while(j!=0){
            k=y[j];
            tot++;
            dfs(k);
            j=next[j];
        }
    }
    
    Tree Merge(Tree a,Tree b)
    {
        Tree c;
        c.mn=min(a.mn,b.mn);
        if(a.mx>b.mx){
            c.mx=a.mx;
            c.id=a.id;
        }
        else{
            c.mx=b.mx;
            c.id=b.id;
        }
        return c;
    }
    
    void build(int l,int r,int t)
    {
        if(l==r){
            tr[t].mn=-H[l].top();
            if(l!=1)tr[t].mx=sz[l]*2;
            else tr[t].mx=0;
            tr[t].id=l;
            return;
        }
        int mid;
        mid=(l+r)/2;
        build(l,mid,t+t);
        build(mid+1,r,t+t+1);
        tr[t]=Merge(tr[t+t],tr[t+t+1]);
    }
    
    void insert(int t,int l,int r,int x,int y,int z)
    {
        if(l==r){
            if(z==0)tr[t].mx+=y;
            else tr[t].mn=y;
            return;
        }
        int mid;
        mid=(l+r)/2;
        if(x<=mid)insert(t+t,l,mid,x,y,z);
        if(x>mid)insert(t+t+1,mid+1,r,x,y,z);
        tr[t]=Merge(tr[t+t],tr[t+t+1]);
    }
    
    Tree ask(int t,int l,int r,int x,int y)
    {
        if(x>y)return emp;
        if(l==x&&r==y)return tr[t];
        int mid;
        mid=(l+r)/2;
        if(y<=mid)return ask(t+t,l,mid,x,y);
        if(x>mid)return ask(t+t+1,mid+1,r,x,y);
        if(x<=mid&&y>mid)return Merge(ask(t+t,l,mid,x,mid),ask(t+t+1,mid+1,r,mid+1,y));
    }
    
    void Work()
    {
        int i,mi,mn,sum;
        Tree Tl,Tr;
        for(i=1;i<=n;i++)Ans+=dis[i];
        Ans*=2;
        printf("%I64d
    ",Ans);
        build(1,tot,1);
        sum=n;
        emp.mn=2147483646;
        for(i=1;i<=n;i++){
            if(bel[i]!=1){
                Tl=ask(1,1,tot,1,bel[i]-1);
                Tr=ask(1,1,tot,bel[i]+1,tot);
                mn=min(Tl.mn,Tr.mn);
            }
            else mn=tr[1].mn;
            insert(1,1,tot,bel[i],-1,0);
            insert(1,1,tot,bel[mn],-1,0);
            if(tr[1].mx>sum-1){
                mi=tr[1].id;
                insert(1,1,tot,bel[mn],1,0);
                insert(1,1,tot,mi,-1,0);
                ans[i]=-H[mi].top();
                H[mi].pop();
                if(!H[mi].empty())insert(1,1,tot,mi,-H[mi].top(),1);
                else insert(1,1,tot,mi,2147483646,1);
            }
            else{
                ans[i]=mn;
                H[bel[mn]].pop();
                if(!H[bel[mn]].empty())insert(1,1,tot,bel[mn],-H[bel[mn]].top(),1);
                else insert(1,1,tot,bel[mn],2147483646,1);
            }
            sum--;
        }
        for(i=1;i<n;i++)printf("%d ",ans[i]);
        printf("%d
    ",ans[n]);
    }
    
    int main()
    {
        scanf("%d",&n);
        for(i=1;i<n;i++){
            scanf("%d%d%d",&x,&z,&q);
            star(x,z,q);
            star(z,x,q);
        }
        Bfs(1);
        Bfs(root);
        Prepare();
        Work();
    }
  • 相关阅读:
    bzoj4734
    51nod1056
    51nod1048
    51nod1248
    51nod1044
    51nod1132
    51nod1146
    51nod1226
    Spring Boot: Jdbc javax.net.ssl.SSLException: closing inbound before receiving peer's close_notify
    sqlserver命令创建数据库和表 demo
  • 原文地址:https://www.cnblogs.com/applejxt/p/4476177.html
Copyright © 2011-2022 走看看