n<=300000个点的树,给m<=300000条带权路径(ui,vi,保证vi是ui的祖先)求覆盖整棵树每条边的最小权和。

好题好姿势!直观的看到可以树形DP,f[i]表示把点i包括它爸爸下面那条边都覆盖的最小权,就用经过他爸爸那条边的所有路径,各条路径加上一些子树信息来更新即可。

这样时间炸,那看看怎么优化。实际上我们不是在单纯地用一条路径更新答案,而是这样一个东西:

其中红色那条是题目给的路径,实际上是加上蓝色边连接的点的f[i]来更新边2上端的那个点的答案的。也就是说,一条路径来更新答案,要在这条路径的尾部加上那些点权(1),然后在更新某个点的答案的时候加上这个点下面的这条路径的分叉(2)。而更新一个点的路径,其实都是这个点对应子树的路径。至于子树中那些够不到这个点的路径,只需在扫到头的时候把这条路径的答案变inf即可。

为了实现这个操作,即找到“起点在子树里的所有路径的答案”,我们用dfs序给每个路径的起点(下端点)编号,再dfs求每个点的答案;每次求答案时,先把以该点为起点的新路径赋初值,即该点所有子树的f[j]和,并把终点在该点的路径答案置inf;然后给经过该点的路径加“分叉”;由于dfs序编号好了,能更新这个节点的路径(上面提到的起点在这个子树内的路径)是连续的一个区间,因此用个线段树维护区间min即可。

至于加“分叉”,观察可以发现:假如经过i的某路径来自子树j,那么应该把它答案加上点i其他儿子的f和。所以在加“分叉”时只需要再枚举一次孩子,把孩子子树内所有的路径加上其他孩子的f[j]和即可。

废话少说见代码!

 #include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<algorithm>
//#include<iostream>
using namespace std; int n,m;
#define maxn 300011
struct Edge{int to,next;}edge[maxn*];int first[maxn],start[maxn],end[maxn],le=;
void in(int x,int y,int* first) {edge[le].to=y;edge[le].next=first[x];first[x]=le++;}
void insert(int x,int y,int* first) {in(x,y,first);in(y,x,first);}
int dfn[maxn],Left[maxn],Right[maxn],Time=;
void dfs(int x,int fa)
{
Left[x]=Time+;
for (int i=start[x];i;i=edge[i].next)
{
Edge &e=edge[i];
dfn[e.to]=++Time;
}
for (int i=first[x];i;i=edge[i].next)
{
Edge &e=edge[i];
if (e.to!=fa) dfs(e.to,x);
}
Right[x]=Time;
}
#define LL long long
LL val[maxn];
const LL inf=1e15+;
struct SMT
{
struct Node
{
LL Min;
LL add;
int l,r;
int ls,rs;
}a[maxn*];
int size;
SMT() {size=;}
void build(int &x,int L,int R)
{
x=++size;
a[x].Min=inf;a[x].add=;
a[x].l=L;a[x].r=R;
if (L==R) {a[x].ls=a[x].rs=;}
else
{
const int mid=(L+R)>>;
build(a[x].ls,L,mid);
build(a[x].rs,mid+,R);
}
}
void build() {int x;build(x,,m);}
void up(int x)
{
const int &p=a[x].ls,&q=a[x].rs;
a[x].Min=min(a[p].Min,a[q].Min);
}
void addsingle(int x,LL v)
{
a[x].Min+=v;
a[x].Min=min(inf,a[x].Min);
a[x].add+=v;
}
void down(int x)
{
const int &p=a[x].ls,&q=a[x].rs;
if (a[x].add)
{
addsingle(p,a[x].add);
addsingle(q,a[x].add);
a[x].add=;
}
}
int ql,qr;LL v;
void be(int x)
{
if (a[x].l==a[x].r) {a[x].Min=v;return;}
down(x);
const int mid=(a[x].l+a[x].r)>>;
if (ql<=mid) be(a[x].ls);
if (ql> mid) be(a[x].rs);
up(x);
}
void be(int p,LL v) {ql=qr=p;this->v=v;be();}
void Add(int x)
{
if (ql<=a[x].l && a[x].r<=qr) {addsingle(x,v);return;}
down(x);
const int mid=(a[x].l+a[x].r)>>;
if (ql<=mid) Add(a[x].ls);
if (qr> mid) Add(a[x].rs);
up(x);
}
void Add(int L,int R,LL v) {if (L>R) return;ql=L;qr=R;this->v=v;Add();}
LL query(int x)
{
if (ql<=a[x].l && a[x].r<=qr) return a[x].Min;
down(x);
const int mid=(a[x].l+a[x].r)>>;LL ans=inf;
if (ql<=mid) ans=min(ans,query(a[x].ls));
if (qr> mid) ans=min(ans,query(a[x].rs));
return ans;
}
LL query(int L,int R) {if (L>R) return inf;ql=L;qr=R;return query();}
}t;
LL f[maxn];
void play(int x,int fa)
{
LL tot=;
for (int i=first[x];i;i=edge[i].next)
{
Edge &e=edge[i];if (e.to==fa) continue;
play(e.to,x);
tot=min(inf,f[e.to]+tot);
}
for (int i=start[x];i;i=edge[i].next)
{
Edge &e=edge[i];
t.be(dfn[e.to],tot+val[e.to]);
}
for (int i=end[x];i;i=edge[i].next)
{
Edge &e=edge[i];
t.be(dfn[e.to],inf);
}
if (x==) f[]=tot;
else if (tot<inf)
{
for (int i=first[x];i;i=edge[i].next)
{
Edge &e=edge[i];if (e.to==fa) continue;
t.Add(Left[e.to],Right[e.to],tot-f[e.to]);
}
f[x]=t.query(Left[x],Right[x]);
}
else f[x]=inf;
}
void play()
{
dfs(,);
t.build();
play(,);
}
int x,y;LL v;
int main()
{
scanf("%d%d",&n,&m);
for (int i=;i<n;i++)
{
scanf("%d%d",&x,&y);
insert(x,y,first);
}
for (int i=;i<=m;i++)
{
scanf("%d%d%I64d",&x,&y,&val[i]);
in(x,i,start);
in(y,i,end);
}
play();
printf(f[]>=inf?"-1\n":"%I64d\n",f[]);
return ;
}

还有一种贪心写法哦!

CF671D:Roads in Yusland的更多相关文章

  1. 【CF671D】Roads in Yusland(贪心,左偏树)

    [CF671D]Roads in Yusland(贪心,左偏树) 题面 洛谷 CF 题解 无解的情况随便怎么搞搞提前处理掉. 通过严密(大雾)地推导后,发现问题可以转化成这个问题: 给定一棵树,每条边 ...

  2. 【CF671D】 Roads in Yusland(对偶问题,左偏树)

    传送门 洛谷翻译 CodeForces Solution emmm,先引入一个对偶问题的概念 \(max(c^Tx|Ax \leq b)=min(b^Ty|A^Ty \ge c)\) 考虑这个式子的现 ...

  3. Codeforces 671 D. Roads in Yusland

    题目描述 Mayor of Yusland just won the lottery and decided to spent money on something good for town. Fo ...

  4. [Codeforces671D]Roads in Yusland

    [Codeforces671D]Roads in Yusland Tags:题解 题意 luogu 给定以1为根的一棵树,有\(m\)条直上直下的有代价的链,求选一些链把所有边覆盖的最小代价.若无解输 ...

  5. 【CF617D】Roads in Yusland

    [CF617D]Roads in Yusland 题面 蒯的洛谷的 题解 我们现在已经转化好了题目了,戳这里 那么我们考虑怎么求这个东西,我们先判断一下是否所有的边都能被覆盖,不行的话输出\(-1\) ...

  6. 【CodeForces】671 D. Roads in Yusland

    [题目]D. Roads in Yusland [题意]给定n个点的树,m条从下往上的链,每条链代价ci,求最少代价使得链覆盖所有边.n,m<=3*10^5,ci<=10^9,time=4 ...

  7. codesforces 671D Roads in Yusland

    Mayor of Yusland just won the lottery and decided to spent money on something good for town. For exa ...

  8. CF671D Roads in Yusland

    一道很玄妙的题= = 我们考虑先考虑DP 那么有$f[x]=min(c+\sum f[y])$ $f[x]$表示覆盖x的子树和x->fa[x]的所有边最小代价 我们枚举一条边c覆盖的x-> ...

  9. 题解-Codeforces671D Roads in Yusland

    Problem Codeforces-671D 题意概要:给定一棵 \(n\) 点有根树与 \(m\) 条链,链有费用,保证链端点之间为祖先关系,问至少花费多少费用才能覆盖整棵树(\(n-1\) 条边 ...

随机推荐

  1. iOS 开发App捕获异常, 反馈给服务器, 提高用户体验

    在我们开发的app中, 不可避免的, 有时候用户使用软件会崩溃.  我们就需要捕获异常, 可以在入口类中加入相应的代码, 可以在每次用户打开程序的时候, 检查一下沙盒中是否有崩溃日志, 如果有, 可以 ...

  2. SQLServer · 最佳实践 · SQL Server 2012 使用OFFSET分页遇到的问题

    1. 背景 最近有一个客户遇到一个奇怪的问题,以前使用ROW_NUMBER来分页结果是正确的,但是替换为SQL SERVER 2012的OFFSET...FETCH NEXT来分页出现了问题,因此,这 ...

  3. github 下载全部项目

    从github下载资料过程中,有些项目含有子模块,有时通过git clone 或者下载zip方式项目可能会缺少文件,因此需要执行 git submodule update --init --recur ...

  4. HashSet LinkedHashSet TreeSet 分析

    1.HashSet分析 hashset 底层是hash表,就是hashMap,是无序的,唯一的.也就是说,它的底层其实就是一个HashMap  key 值的组成值.所以具有唯一性. public Ha ...

  5. Linux之vi(vim)编辑器

    命令行模式:默认进来就是命令行模式 ,可以使用很多命令:比如i . a . o i:光标前面输入内容 a:光标的下一位字符开始输入内容 o:光标的下一行开始输入内容 编辑模式: 退出编辑模式:键盘上e ...

  6. 《3+1团队》【Alpha】Scrum meeting 1

    项目 内容 这个作业属于哪个课程 任课教师博客主页链接 这个作业的要求在哪里 作业链接地址 团队名称 3+1团队 团队博客地址 https://home.cnblogs.com/u/3-1group ...

  7. 2019西安多校联训 Day5

    T1 光哥为了不让某初二奆佬恶心到我们而留下的火种 (貌似没这题平均分就100-了) 思路:就一横一竖让后就gztopa嘛 #include <bits/stdc++.h> using n ...

  8. 【简●解】[HAOI2007] 理想的正方形

    [简●解][HAOI2007] 理想的正方形 可恶的\(DP\). [题目大意] 有一个\(a*b\)的整数组成的矩阵,现请你从中找出一个\(n*n\)的正方形区域,使得该区域所有数中的最大值和最小值 ...

  9. [JOYOI] 1124 花店橱窗

    题目限制 时间限制 内存限制 评测方式 题目来源 1000ms 131072KiB 标准比较器 Local 题目背景 xq和他的老婆xz最近开了一家花店,他们准备把店里最好看的花都摆在橱窗里.但是他们 ...

  10. 如何用纯 CSS 创作一个金属光泽 3D 按钮特效

    效果预览 在线演示 按下右侧的"点击预览"按钮在当前页面预览,点击链接全屏预览. https://codepen.io/zhang-ou/full/MGeRRO 可交互视频教程 此 ...