题目描述:

$zhx$有一个棵$n$个点的树,每条边有个权值。

定义一个连通块为一个点集与使这些点连通的所有边(这些点必须连通)。

定义一个连通块的权值为这个连通块的边权和(如果一个连通块只包含一个点,那么它的权值为$0$)。

$zhx$想找一个包含$1$号点的连通块送给他的妹子,所以他希望你求出包含$1$号点的所有连通块中权值第$k$小的连通块的权值。

题解:

非常裸的可持久化可并堆。

经典的$k$短路要求维护绕多远+终点,而它维护总边权+可选边集。

维护边集时需要可持久化可并堆。

还是经典操作,要么扔掉上一条边换上次优,要么在边集中找一个最优然后更新边集。

代码:

#include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = ;
const int MOD = ;
const int M = *N;
typedef long long ll;
template<typename T>
inline void read(T&x)
{
T f = ,c = ;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){c=c*+ch-'';ch=getchar();}
x = f*c;
}
int n,k,rt[N],wy[M];
ll ww[M];
struct edc
{
int x;
ll d;
edc(){}
edc(int x,ll d):x(x),d(d){}
friend bool operator < (edc a,edc b)
{
return a.d>b.d;
}
}tp;
int tot,tw;
struct node
{
int ls,rs,dis,tl;
ll v;
}p[M];
int merge1(int x,int y)
{
if(!x||!y)return x+y;
if(p[x].v>p[y].v)swap(x,y);
p[x].rs = merge1(p[x].rs,y);
if(p[p[x].ls].dis<p[p[x].rs].dis)swap(p[x].ls,p[x].rs);
p[x].dis=p[p[x].rs].dis+;
return x;
}
int merge(int x,int y)
{
if(!x||!y)return x+y;
if(p[x].v>p[y].v)swap(x,y);
int u = ++tot;
p[u] = p[x],p[u].rs = merge(p[u].rs,y);
if(p[p[u].ls].dis<p[p[u].rs].dis)swap(p[u].ls,p[u].rs);
p[u].dis = p[p[u].rs].dis+;
return u;
}
priority_queue<edc>q;
ll ans;
int main()
{
freopen("tt.in","r",stdin);
read(n),read(k);
for(int f,w,i=;i<n;i++)
{
read(f),read(w);
p[++tot].dis=,p[tot].tl=i+,p[tot].v=w;
rt[f] = merge1(rt[f],tot);
}
k--;
tw=;
ww[tw] = p[rt[]].v;
wy[tw] = rt[];
q.push(edc(,ww[]));
while(k&&!q.empty())
{
tp = q.top();
q.pop();
k--;
int u = tp.x;
ans = ww[u];
if(!k)break;
int ls = p[wy[u]].ls,rs = p[wy[u]].rs;
int tmp = merge(ls,rs);
if(tmp)
{
tw++;
ww[tw] = ww[u]-p[wy[u]].v+p[tmp].v;
wy[tw] = tmp;
q.push(edc(tw,ww[tw]));
}
tw++;
wy[tw] = merge(tmp,rt[p[wy[u]].tl]);
ww[tw] = ww[u]+p[wy[tw]].v;
if(wy[tw])q.push(edc(tw,ww[tw]));
}
printf("%lld\n",ans%MOD);
return ;
}

OVOO的更多相关文章

  1. 【CH 弱省互测 Round #1 】OVOO(可持久化可并堆)

    Description 给定一颗 \(n\) 个点的树,带边权. 你可以选出一个包含 \(1\) 顶点的连通块,连通块的权值为连接块内这些点的边权和. 求一种选法,使得这个选法的权值是所有选法中第 \ ...

  2. IntelliJ IDEA sass环境配置及常见报错处理

    1.下载安装ruby,网上教程很多的,安装完之后在命令行输入ruby -v检查一下是否安装成功了.(注意安装的时候要勾选第二项).

  3. GitHub创建个人主页

    在GitHub,一个项目对应唯一的Git版本库,创建一个新的版本库就是创建一个新的项目.访问仪表板(Dashboard)页面,如图3-1,可以看 到关注的版本库中已经有一个,但自己的版本库为零.在显示 ...

  4. 面向初学者的指南:创建时间序列预测 (使用Python)

    https://blog.csdn.net/orDream/article/details/100013682 上面这一篇是对 https://www.analyticsvidhya.com/blog ...

随机推荐

  1. mfc基于对话框的应用程序,如何设置初始对话框大小,移动控件位置

    void MmPLEntPropertyDlg::SetInitDialogSize() { CRect rectDlg; GetWindowRect(rectDlg);//x,y为对话框左上角的坐标 ...

  2. 超完整的Chrome浏览器客户端调试大全

    引言 “工欲善其事,必先利其器” 没错,这句话个人觉得说的特别有道理,举个例子来说吧,厉害的化妆师都有一套非常专业的刷子,散粉刷负责定妆,眼影刷负责打眼影,各司其职,有了专业的工具才能干专业的事,这个 ...

  3. Mac 解登录密码Keychain

    在终端输入: security unlock-keychain -p "login pwd" ~/Library/Keychains/login.keychain 在制作macOS ...

  4. Hdu 5496 Beauty of Sequence (组合数)

    题目链接: Hdu 5496 Beauty of Sequence 题目描述: 一个整数序列,除去连续的相同数字(保留一个)后,序列的和成为完美序列和.问:一个整数序列的所有子序列的完美序列和? 解题 ...

  5. Kruskal && Prim模板

    1. Kruskal(并查集模板): /* Kruskal:并查集实现,记录两点和距离,按距离升序排序,O (ElogE) */ struct Edge { int u, v, w; bool ope ...

  6. Kruskal HDOJ 1233 还是畅通工程

    题目传送门 /* 最小生成树之kruskal算法--并查集(数据结构)实现 建立一个结构体,记录两点和它们的距离,依照距离升序排序 不连通就累加距离,即为最小生成树的长度 */ #include &l ...

  7. synchronized(6)修饰语方法之:static方法

    当一个synchronized关键字修饰的方法同时又被static修饰,之前说过,非静态的同步方法会将对象上锁,但是静态方法不属于对象,而是属于类,它会将这个方法所在的类的Class对象上锁. 一个类 ...

  8. Contextual Action bar(3) 两个示例

    一.通过activity启动Context Action Bar 1.主java public class ActivityActionModeFrgmt extends Fragment imple ...

  9. jmeter(十八)属性和变量

    一.Jmeter中的属性: 1.JMeter属性统一定义在jmeter.properties文件中,我们可以在该文件中添加自定义的属性 2.JMeter属性在测试脚本的任何地方都是可见的(全局),通常 ...

  10. Unity项目学习笔记

    1.TCP和IP IP:主要作用是在复杂的网络环境中将数据包发送给的最终的目标地址. 端口号:系统会分给系统端口号  一般知名的端口号在0-1023之间,而我们经常使用的自定义/动态分配的端口号则一般 ...