【CF671D】Roads in Yusland

技术【CF671D】Roads in Yusland 【CF671D】Roads in Yusland题目
题目链接:https://codeforces.com/problemset/problem/

【CF671D】尤斯兰的道路

题目

题目链接:https://codeforces.com/problemset/problem/671/D

给定一棵\(n\)个点的以\(1\) 为根的树。

有\(m\)条路径\((x,y)\),保证\(y\)是\(x\)或\(x\)的祖先,每条路径有一个权值。

你要在这些路径中选择若干条路径,使它们能覆盖每条边,同时权值和最小。

《10^5\)。时报》

思路

设\(f[x]\)表示覆盖点\(x\)子树内所有边以及\(x\)与其父亲的边的最小代价。

但是很明显\(f[x]\)不能简单转移。因为有可能花更多代价,覆盖\(x\)的祖先更多,这种情况是可能最优的。

所以可以对每一个点维护一个堆,存可能的最优解。

考虑点\(y\)怎么转移到其父亲\(x\)。对于\(y\)的堆中一个代价为\(k\)的方案,合并到\(x\)后,其代价应该是\(k \\ sum _ { z \\ in \\ text { son }(x),z \\ neq y \u f[z]\)。

也就是说,\(y\)的所有方案只需要同时加上一个常数,然后扔到\(x\)的堆里就好了。直接上左偏树,然后需要搞一个子树加的标记。

但是当某一个方案覆盖不到\(x\)与其父亲的边的时候,这个方案就需要删掉了。在每次合并完后不断判断堆顶是否需要删掉即可。

新建一个虚根连向\(1\),再加一条代价为\(0\) 的路径,最后输出虚根的\(f\)即可。

时间复杂度\(0(n \ log m)\)。

代码

#包含位/stdc .h

#定义国会议员制作对

#首先定义船方不负担装货费用

#定义硒秒

使用命名空间标准;

typedef长ll长

常量整数N=300010

整数n,m,tot,头[N],rt[N],副[N];

ll f[N];

布尔标志;

vectorpairint,int a[N];

结构边缘

{

(同Internationalorganizations)国际组织紧挨着;

} e[N * 2];

void add(int from,int to)

{

e[ tot]=(edge){head[from],to };

从头开始。

}

结构左树

{

int tot,dis[N],pos[N],lc[N],RC[N];

懒惰的;

int insert(pairint,int b)

{

tot val[tot]=b . se;pos[tot]=b . fi;

返回小孩

}

无效下推(int x)

{

如果(懒惰[x])

{

if (lc[x]) val[lc[x]]=lazy[x],lazy[LC[x]]=lazy[x];

if (rc[x]) val[rc[x]]=lazy[x],lazy[RC[x]]=lazy[x];

lazy[x]=0;

}

}

int merge(int x,int y)

{

if(!x ||!y)返回x | y;

下推;下推(y);

if(val[x]val[y]| |(val[x]==val[y]xy))swap(x,y);

rc[x]=merge(rc[x],y);

if(dis[RC[x]]dis[LC[x]]交换(LC[x],RC[x]);

dis[x]=dis[RC[x]]1;

返回x;

}

int pop(int x)

{

下推;

返回合并(lc[x],RC[x]);

}

}点亮;

无效dfs(int x,int fa)

{

dep[x]=dep[fa]1;

for(int I=0;i(int)a[x].size();(一)

rt[x]=lit.merge(rt[x],lit)。插入(a[x][I]);

for(int I=head[x];~我;i=e[i]。下一个)

{

int v=e[i].去;

if (v!=fa)

{

dfs(v,x);f[x]=f[v];

如果(标志)返回;

真实的懒惰[rt[v]]-=f[v];真实的val[rt[v]]-=f[v];

rt[x]=lit.merge(rt[x],rt[v]);

}

}

真实的lazy[rt[x]]=f[x];真实的val[rt[x]]=f[x];

而(rt[x]dep[lit]。pos[rt[x]]=dep[x])

rt[x]=点亮。pop(rt[x]);

if(!rt[x]){ flag=1;返回;}

f[x]=升。val[rt[x]];

}

int main()

{

memset(head,-1,sizeof(head));

scanf('%d%d ',n,m);

for (int i=1,x,y;在;(一)

{

scanf('%d%d ',x,y);

添加(x,y);添加(y,x);

}

n;add(n,1);

for (int i=1,x,y,z;I=m;(一)

{

scanf('%d%d%d ',x,y,z);

a[x].push_back(mp(y,z));

}

a[1].push_back(mp(0,0));

真实的dis[0]=-1;dep[0]=-1;

dfs(n,0);

如果(标志)cout '-1 ';

else coutf[n];

返回0;

}

内容来源网络,如有侵权,联系删除,本文地址:https://www.230890.com/zhan/37483.html

(0)

相关推荐

  • c++实现打印结构体所有变量

    技术c++实现打印结构体所有变量 c++实现打印结构体所有变量说明
    c++没有静态反射机制,这里采用暴力解析头文件,并生成代码的形式
    有struct定义解析结构体
    /*
    ---- From XDU's

    礼包 2021年10月19日
  • VB.NET局部静态变量怎么用

    技术VB.NET局部静态变量怎么用这篇文章主要为大家展示了“VB.NET局部静态变量怎么用”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“VB.NET局部静态变量怎么用”这篇文

    攻略 2021年12月2日
  • Phone类的怎么实现

    技术Phone类的怎么实现这篇文章主要讲解了“Phone类的怎么实现”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Phone类的怎么实现”吧! Decorat

    攻略 2021年12月8日
  • vue+elementui如何实现下拉表格多选和搜索功能

    技术vue+elementui如何实现下拉表格多选和搜索功能这篇文章主要介绍“vue+elementui如何实现下拉表格多选和搜索功能”,在日常操作中,相信很多人在vue+elementui如何实现下拉表格多选和搜索功能

    攻略 2021年11月26日
  • 怎么在Ubuntu 18.04服务器上安装TensorFlow

    技术怎么在Ubuntu 18.04服务器上安装TensorFlow小编给大家分享一下怎么在Ubuntu 18.04服务器上安装TensorFlow,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读

    攻略 2021年11月18日
  • JavaScript是怎么运行的

    技术JavaScript是怎么运行的这篇文章主要讲解了“JavaScript是怎么运行的”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“JavaScript是怎么运行的”吧

    攻略 2021年11月20日