Broken Tree(CF-758E) - 竞赛题解

贪心复习~(好像暴露了什么算法……)

标签:贪心 / DFS / Codeforces


『题意』

给出一棵以1为根的树,每条边有两个值:p-强度、w-重量。

对于给出的树,我们可以对每条边进行操作——将它的p、w同时减去相同的值,但是要求 \(p\ge0,w>0\) 。(注意只能减,不能加

进行操作后,需要使原树满足:如果 u 是 v 的父亲,那么 u 到 v 的边的 p 不能小于 以 v 为根节点的子树中所有边的 w 之和。

求出一种方案,使得在满足条件的情况下,树的 w 之和最大,输出这个方案。如果不存在任何方案,输出-1(Of course 有 SPJ)


『解析』

简单地思考一下,对于这道题,叶子节点的p以及与根节点相连的边的w是没有用的……

根据这个我们可以想出一个思路——从下到上尽可能减去重量,求到重量最小的树;再从上到下贪心地尽可能给每条边加重量(不超过原重量),得到答案。比较有趣的是正解好像也是这么写的——因为按理来说样例的解很多,但是我的程序跑出来是一样的~

「减重量-DFS」

从根节点DFS到叶子节点,然后从叶子节点递归得到整个树的最小重量解(当然是唯一解)

声明一下变量:

(1) edg[i] 按照输入顺序给出的第i条边(从1开始);

(2) fedg[i] 对应edg[i],表示修改后的第i条边;

(3) pnt[i] 表示以i为根的子树的最小总重量(满足条件的);

(4) (u,v) 表示 u,v 之间的边在输入时的顺序

Tab. edg,fedg 都是结构体,包含元素 wgt,ref 分别表示重量、强度

假设现在是 u点,已经计算出它的儿子 v,边的编号 id=(u,v)。

首先判断重量是否合法——如果子树v的最小重量 pnt[v] 都大于 edg[id].ref 了,那么就不合法,输出-1。

否则,显然如果不考虑 \(edg[id].wgt>0\) ,那么我们可以把 edg[id].ref 降至 pnt[v] —— 那么我们就是要在 \(edg[id].wgt>0\) 的情况下尽可能的使 edg[id].ref 小。计算 \(delta\) 表示将 edg[id] 的 wgt 和 ref 同时减去 delta。那么 \(delta=min\{edg[id].ref-hvy\ ,\ edg[id].wgt-1\}\),将削减后的值存入 fedg[id] ,最后统计 pnt[u] 。

这样我们就求出了最小重量的方案(同时判断了不存在解的情况)。

「增重量-Solve」

根据最开始的分析,我们可以将与根节点相连的所有边的 wgt 和 ref 都调至最大(也就是初始值)。

在 Solve() 函数中除了 当前节点u 还附带一个变量 \(del\)表示u的子树在最小基础下的能够增加的最大重量。其实Solve()的本质还是一个 DFS……但是它的返回值是 以u为根的子树中在最小重量的基础上新增加的重量之和,所以我们用deltot来记录这个返回值。

那么从根节点出发,我们可以把 del 看做是正无穷,因为没有任何限制。

假设现在正在处理 边(u,v) ,u是父亲。

如果当前边再加上 del 不超过原来的重量,那么就可以将它加上,返回 deltot+=del(这里del就相当于加重量的机会,而这种情况就相当于把所有机会用完了)。

否则在给当前边增加重量后,del还有剩余——那么就贪心地把 del 分配到 v 里去。也就是先给 边(u,v) 加大到可能的最大值,同时将 del 减去增加的值。但是我们不能直接将 del 下传到 v 去,因为可能 v 的子树在增加 del 的重量后,边(u,v) 的强度不够,所以下传时,我们进行一个处理—— \(min(del,fedg[id].ref-pnt[v])\)(这里的pnt[v]其实就是在未对v进行 Solve() 修改时的v的子树总重)。最后在 Solve() 返回时将 del 减去其返回值,表示用去了这么多“机会”。

然后就可以了~


『源代码』

/*Lucky_Glass*/
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=(int)2e5;
struct GRAPH{
struct NODE{
int to,nxt,id;
NODE(){}
NODE(int _to,int _nxt,int _id):to(_to),nxt(_nxt),id(_id){}
}nod[N*2+7];
int adj[N+7],cnt,siz[N+7];
GRAPH(){memset(adj,-1,sizeof adj);cnt=0;}
void AddEdge(int u,int v,int id,bool dir){
siz[u]++;nod[++cnt]=NODE(v,adj[u],id);adj[u]=cnt;
if(!dir) AddEdge(v,u,id,true);
}
}grp;
struct EDGE{
int u,v;
long long ref,wgt;
}edg[N+7],fedg[N+7];
int n;
long long pnt[N+7];
long long DFS(int u,int pre){
long long hvytot=0;
for(int i=grp.adj[u];i!=-1;i=grp.nod[i].nxt){
int v=grp.nod[i].to,id=grp.nod[i].id;
if(v==pre) continue;
long long hvy=DFS(v,u);
if(hvy>edg[id].ref){
printf("-1\n");
exit(0);
}
long long delta=min(edg[id].ref-hvy,edg[id].wgt-1);
fedg[id].ref=edg[id].ref-delta;
fedg[id].wgt=edg[id].wgt-delta;
hvytot+=hvy+fedg[id].wgt;
}
return pnt[u]=hvytot;
}
long long Solve(int u,int pre,long long del){ //del:u的子树在最小基础下的能够增加的最大重量
long long deltot=0;
for(int i=grp.adj[u];i!=-1;i=grp.nod[i].nxt){
int v=grp.nod[i].to,id=grp.nod[i].id;
if(v==pre) continue;
if(fedg[id].wgt+del<=edg[id].wgt){
fedg[id].wgt+=del;fedg[id].ref+=del;
deltot+=del;
del=0;break;
}
else{
deltot+=edg[id].wgt-fedg[id].wgt;
del-=edg[id].wgt-fedg[id].wgt;
fedg[id]=edg[id];
}
long long delv=Solve(v,u,min(del,fedg[id].ref-pnt[v]));
del-=delv;deltot+=delv;
}
return deltot;
}
int main(){
scanf("%d",&n);
for(int i=1;i<n;i++){
scanf("%d%d%d%d",&edg[i].u,&edg[i].v,&edg[i].wgt,&edg[i].ref);
fedg[i]=edg[i];
grp.AddEdge(edg[i].u,edg[i].v,i,false);
}
DFS(1,0);
Solve(1,0,(1ll<<60));
printf("%d\n",n);
for(int i=1;i<n;i++)
printf("%d %d %lld %lld\n",fedg[i].u,fedg[i].v,fedg[i].wgt,fedg[i].ref);
return 0;
}

\(\mathcal{The\ End}\)

\(\mathcal{Thanks\ For\ Reading!}\)

- 如果blog里面有没讲清楚的……可以在我的邮箱\(lucky\_glass@foxmail.com\)问我~

竞赛题解 - Broken Tree(CF-758E)的更多相关文章

  1. 竞赛题解 - CF Round #524 Div.2

    CF Round #524 Div.2 - 竞赛题解 不容易CF有一场下午的比赛,开心的和一个神犇一起报了名 被虐爆--前两题水过去,第三题卡了好久,第四题毫无头绪QwQ Codeforces 传送门 ...

  2. 竞赛题解 - [CF 1080D]Olya and magical square

    Olya and magical square - 竞赛题解 借鉴了一下神犇tly的博客QwQ(还是打一下广告) 终于弄懂了 Codeforces 传送门 『题目』(直接上翻译了) 给一个边长为 \( ...

  3. 《ACM国际大学生程序设计竞赛题解Ⅰ》——基础编程题

    这个专栏开始介绍一些<ACM国际大学生程序设计竞赛题解>上的竞赛题目,读者可以配合zju/poj/uva的在线测评系统提交代码(今天zoj貌似崩了). 其实看书名也能看出来这本书的思路,就 ...

  4. 竞赛题解 - Karp-de-Chant Number(BZOJ-4922)

    Karp-de-Chant Number(BZOJ-4922) - 竞赛题解 进行了一次DP的练习,选几道题写一下博客~ 标签:BZOJ / 01背包 / 贪心 『题目』 >> There ...

  5. 竞赛题解 - Palisection(CF-17E)

    Palisection(CF-17E) - 竞赛题解 Manacher学到一定程度,也需要练一下有趣的题了-- (这是多老的题了 \(QwQ\))[传送门] 『题意』 给出一个字符串,求总共有多少对不 ...

  6. 竞赛题解 - NOIP2018 保卫王国

    \(\mathcal{NOIP2018}\) 保卫王国 - 竞赛题解 按某一个炒鸡dalao名曰 taotao 的话说: \(\ \ \ \ \ \ \ \ \ "一道sb倍增题" ...

  7. 竞赛题解 - NOIP2018 旅行

    \(\mathcal {NOIP2018} 旅行 - 竞赛题解\) 坑还得一层一层的填 填到Day2T1了 洛谷 P5022 题目 (以下copy自洛谷,有删减/修改 (●ˇ∀ˇ●)) 题目描述 小 ...

  8. 竞赛题解 - NOIP2018 赛道修建

    \(\mathcal {NOIP2018}\) 赛道修建 - 竞赛题解 额--考试的时候大概猜到正解,但是时间不够了,不敢写,就写了骗分QwQ 现在把坑填好了~ 题目 (Copy from 洛谷) 题 ...

  9. 竞赛题解 - Ikki's Story IV-Panda's Trick

    Ikki's Story IV-Panda's Trick - 竞赛题解 也算是2-sat学习的一个节点吧 终于能够自己解决一道2-sat的题了 ·题目 一个圆上有n个点按顺时针编号为 0~n-1 , ...

随机推荐

  1. 第四次作业-第一次scrum冲刺

    团队成员 周斌 舒 溢 许嘉荣 唐 浩 黄欣欣 1.第一次冲刺任务安排 对Github上的HUSTOJ开源项目进行Fork,搭建基本环境 2.用户需求 ①基本功能显示在首页 ②能够提交题目并判题,并对 ...

  2. Nancy使用Razor视图引擎时,提示对C:\Windows\temp 没有权限访问的问题

    Nancy下使用Razor视图需要添加DLL文件引用,通过Nuget安装: 发布网站,在IIS上建立站点后,提示错误:对C:\Windows\temp\XXXX 的访问被拒绝(在VS里F5调试的时候没 ...

  3. linux下设置eclipse中的项目和类名的字体大小

    由于刚装的eclipse中的项目和类名字体太小,并且windows中没有可以更改的方法, 所以参考了网上一些文章,终于修改成功,所以反馈进行分享,望国内开源风气如stackoverflow一样. 步骤 ...

  4. c#编程指南(五) 扩展方法(Extension Method)

    C# 3.0就引入的新特性,扩展方法可以很大的增加你代码的优美度,扩展方法提供你扩展.NET Framewoke类的扩展途径,书写和规则也简单的要命. 编写扩展方法有下面几个要求: 第一:扩展方法所在 ...

  5. Oracle实例初始化参数详解

    BACKGROUND_DUMP_DEST 显示和设置Oracle数据库相关日志的存放地,Oracle11g后不再可配置,但其值仍可显示相关日志的存放地,对应配置参数为diagnostic_dest U ...

  6. python 字符编码、格式化

      数据类型-布尔值一个布尔值只有True.False两种值,要么是True,要么是False 布尔值可以用and.or和not运算 空值是Python里一个特殊的值,用None表示 Python对b ...

  7. 使用websploit在局域网全自动渗透

    原理为 websploit调用dnsdpoof进行dns欺骗配合神器metasploit的web_autopwn模块进行渗透:特点:过程基本全自动. 终端输入websploit打开websploit: ...

  8. java的串行化

    参考博客:Java 对象的串行化(Serialization) 1,什么是串行化 对象的寿命通常随着生成该对象的程序的终止而终止.有时候,可能需要将对象的状态保存下来,在需要时再将对象恢复.我们把对象 ...

  9. 阅读Configuration源码

    一.阅读类注释 ①.Configuration的实例允许应用程序使用指定的属性映射文件来创建一个SessionFactory. ②.通常在一个应用程序中创建一个单一的Configuration对象,· ...

  10. luogu P3941 入阵曲

    嘟嘟嘟 这道题我觉得跟最大子矩阵那道题非常像,都是O(n4)二维前缀和暴力很好想,O(n3)正解需要点转化. O(n4)暴力就不说啦,二维前缀和,枚举所有矩形,应该能得55分. O(n3)需要用到降维 ...