[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]));
    }
}

时间: 2024-12-15 11:26:05

[51nod][cf468D]1558 树中的配对的相关文章

题目:[Tree]树中的配对(set&amp;思维)

题目 传送门 思路 首先我们解决第一个问题 怎么使值最大? 这个可以通过公式变形来解决 \(ans=\sum_{i=1}^{n}(dep_i+dep_{p_i}-2*dep_{lca_{i,p_i}})=2*\sum_{i=1}^{n}dep_i-2*\sum_{i=1}^{n}dep_{lca_{i,p_i}}\) 下面我们看看这能得到什么 p序列是客观存在的,这是与哪个节点是根节点是没有关系的 所以对于一个固定的根节点,他的最大值也是答案 然而我们已知,对于一个根节点,式子的前半部分的值是固

51nod 配对(求树的重心)

传送门:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1737 给出一棵n个点的树,将这n个点两两配对,求所有可行的方案中配对两点间的距离的总和最大为多少. Input 一个数n(1<=n<=100,000,n保证为偶数) 接下来n-1行每行三个数x,y,z表示有一条长度为z的边连接x和y(0<=z<=1,000,000,000) Output 一个数表示答案 Input示例 6 1 2 1 1 3 1

51Nod 2006 飞行员配对(二分图最大匹配)-匈牙利算法

2006 飞行员配对(二分图最大匹配) 题目来源: 网络流24题 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题  收藏  关注 第二次世界大战时期,英国皇家空军从沦陷国征募了大量外籍飞行员.由皇家空军派出的每一架飞机都需要配备在航行技能和语言上能互相配合的2名飞行员,其中1名是英国飞行员,另1名是外籍飞行员.在众多的飞行员中,每一名外籍飞行员都可以与其他若干名英国飞行员很好地配合.如何选择配对飞行的飞行员才能使一次派出最多的飞机.对于给定的外籍飞行员与英国飞行员的

51Nod 1737 配对(树的重心)

http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1737 题意: 思路: 树的重心. 树的重心就是其所以子树的最大的子树结点数最少,删除这个点后最大连通块的结点数最小,也就说各个连通块尽量平衡. 这道题的话就是先求一个重心,然后求各个点到重心的距离之和. 1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 #inclu

51nod 2006 飞行员配对(二分图最大匹配) 匈牙利匹配

2006 飞行员配对(二分图最大匹配) 题目来源: 网络流24题 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题  收藏  关注 第二次世界大战时期,英国皇家空军从沦陷国征募了大量外籍飞行员.由皇家空军派出的每一架飞机都需要配备在航行技能和语言上能互相配合的2名飞行员,其中1名是英国飞行员,另1名是外籍飞行员.在众多的飞行员中,每一名外籍飞行员都可以与其他若干名英国飞行员很好地配合.如何选择配对飞行的飞行员才能使一次派出最多的飞机.对于给定的外籍飞行员与英国飞行员的

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

第二次世界大战时期,英国皇家空军从沦陷国征募了大量外籍飞行员.由皇家空军派出的每一架飞机都需要配备在航行技能和语言上能互相配合的2名飞行员,其中1名是英国飞行员,另1名是外籍飞行员.在众多的飞行员中,每一名外籍飞行员都可以与其他若干名英国飞行员很好地配合.如何选择配对飞行的飞行员才能使一次派出最多的飞机.对于给定的外籍飞行员与英国飞行员的配合情况,试设计一个算法找出最佳飞行员配对方案,使皇家空 军一次能派出最多的飞机 .对于给定的外籍飞行员与英国飞行员的配合情况,编程找出一个最佳飞行员配对方案,

[51Nod] 配对

https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1737 求出树的重心,跑spfa #include <iostream> #include <cstdio> #include <cmath> #include <cstring> #include <string> using namespace std; const int N = 1e5 + 10; #define

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

第二次世界大战时期,英国皇家空军从沦陷国征募了大量外籍飞行员.由皇家空军派出的每一架飞机都需要配备在航行技能和语言上能互相配合的2名飞行员,其中1名是英国飞行员,另1名是外籍飞行员.在众多的飞行员中,每一名外籍飞行员都可以与其他若干名英国飞行员很好地配合.如何选择配对飞行的飞行员才能使一次派出最多的飞机.对于给定的外籍飞行员与英国飞行员的配合情况,试设计一个算法找出最佳飞行员配对方案,使皇家空 军一次能派出最多的飞机 .对于给定的外籍飞行员与英国飞行员的配合情况,编程找出一个最佳飞行员配对方案,

51nod 2006 飞行员配对(二分图最大匹配) 裸匈牙利算法 求二分图最大匹配题

题目: 题目已经说了是最大二分匹配题, 查了一下最大二分匹配题有两种解法, 匈牙利算法和网络流. 看了一下觉得匈牙利算法更好理解, 然后我照着小红书模板打了一遍就过了. 匈牙利算法:先试着把没用过的左边的点和没用过的右边的点连起来, 如果遇到一个点已经连过就试着把原来的拆掉 把现在这条线连起来看能不能多连上一条线. 总结来说就是试和拆,试的过程很简单,拆的过程由于使用递归写的,很复杂.很难讲清楚,只能看代码自己理会. 代码(有注释): #include <bits\stdc++.h> usin