【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)

相关推荐

  • 如何使用VBS遍历文件或文件夹路径输入文件的所有绝对路径

    技术如何使用VBS遍历文件或文件夹路径输入文件的所有绝对路径这篇文章给大家分享的是有关如何使用VBS遍历文件或文件夹路径输入文件的所有绝对路径的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。源码

    攻略 2021年11月1日
  • 选择物联网数据库的5个步骤分别是什么

    技术选择物联网数据库的5个步骤分别是什么选择物联网数据库的5个步骤分别是什么,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。企业应该通过了解其数据、功能需求以

    攻略 2021年12月2日
  • sparklines的Stripes是什么(sparklines是什么意思)

    技术sparklines的Stripes是什么这篇文章主要介绍“sparklines的Stripes是什么”,在日常操作中,相信很多人在sparklines的Stripes是什么问题上存在疑惑,小编查阅了各式资料,整理出

    攻略 2021年12月16日
  • mysql大数据量分表分区的API接口读取方法是什么

    技术mysql大数据量分表分区的API接口读取方法是什么这篇文章主要讲解了“mysql大数据量分表分区的API接口读取方法是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学

    攻略 2021年12月4日
  • 将怎么组词,将组词,用将字怎么组词

    技术将怎么组词,将组词,用将字怎么组词将字怎么组词 即将将怎么组词、裨将、小将、将指、宿将、将就、武将、上将、健将、将近、激将、 将胸比肚、 备位将相、 出将入相、 将勇兵雄、 将伯之助、 日就月将、 将(jiāng)

    生活 2021年10月29日
  • 如何快速给Hadoop集群加上弹性

    技术如何快速给Hadoop集群加上弹性本篇内容介绍了“如何快速给Hadoop集群加上弹性”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,

    攻略 2021年12月9日