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

相关推荐

  • 怎么解决nginx php-cgi 自动关闭问题

    技术怎么解决nginx php-cgi 自动关闭问题这篇文章主要介绍“怎么解决nginx php-cgi 自动关闭问题”,在日常操作中,相信很多人在怎么解决nginx php-cgi 自动关闭问题问题上存在疑惑,小编查阅

    攻略 2021年10月26日
  • ajax技术的用法(ajax技术怎么用)

    技术Ajax技术怎么用这篇文章主要介绍了Ajax技术怎么用,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。 ajax的作用有:1

    攻略 2021年12月17日
  • python都应用于什么领域

    技术python都应用于什么领域这篇文章主要介绍“python都应用于什么领域”,在日常操作中,相信很多人在python都应用于什么领域问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”pyt

    攻略 2021年10月30日
  • 【强基06】new和init魔法方法的调用顺序和使用规则

    技术【强基06】new和init魔法方法的调用顺序和使用规则 【强基06】__new__和__init__魔法方法的调用顺序和使用规则调用顺序:
    类里面__new__ 方法的执行优先级高于__init_

    礼包 2021年12月17日
  • Sequoiadb中怎么进行分组去重(sql分组去重)

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

    攻略 2021年12月22日
  • C++怎么使用委托构造函数实现所有构造函数的共通动作

    技术C++怎么使用委托构造函数实现所有构造函数的共通动作本篇内容主要讲解“C++怎么使用委托构造函数实现所有构造函数的共通动作”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“C

    攻略 2021年11月29日