Codeforces 1188A 构造

题意:给你一颗树,树的边权都是偶数,并且边权各不相同。你可以选择树的两个叶子结点,并且把两个叶子结点之间的路径加上一个值(可以为负数),问是否可以通过这种操作构造出这颗树?如果可以,输出构造方案。初始树的边权都是0。

思路:A1很简单,只要判断是否有度数为2的点就可以了。对于A2, 由于边权各不相同,所以A1的结论同样适用。现在我们来构造一组答案。官方题解的构造方式是这样的:我们假设要让一个节点u到叶子结点v的路径都加上一个值x,并且知道叶子结点l1, l2都可以到达u,我们执行以下操作:v到l1的路径加上x / 2, v到l2的路径加上x / 2, l1 到 l2的路径加上-x / 2,这样除了u到v的路径,其它路径的值没有变(太菜了,想不到。。。)。那么,我们从树根开始,从上到下逐个构造边权即可。

由于n只有1000,所以实现方式有两种。

第一种很暴力,赋值操作直接暴力加,复杂度O(n ^ 2)。

代码:

#include <bits/stdc++.h>
#define pii pair<int, int>
#define LL long long
using namespace std;
const int maxn = 1010;
vector<pii> G[maxn];
vector<int> son[maxn];
LL add[maxn];
struct node {int x, y;LL z;
};
vector<node> ans;
int root = 1; 
int f[maxn];
void adde(int x, int y, int z) {G[x].push_back(make_pair(y, z));G[y].push_back(make_pair(x, z));
}int dfs(int x, int fa) {f[x] = fa;for (auto y : G[x]) {if(y.first== fa) continue;int tmp = dfs(y.first, x);son[x].push_back(tmp);}if(G[x].size() == 1) {return x;}return son[x][0];
}void update(int x, int p, int val) {while(x != p) {add[x] += val;x = f[x];}
}
void dfs1(int x, int fa) {int cnt = 0;if(x == root) {int y = G[x][0].first;if(G[y].size() == 1) {ans.push_back((node){x, y, G[x][0].second});return;}LL tmp = G[x][0].second;ans.push_back((node){son[y][0], root, tmp / 2});ans.push_back((node){son[y][1], root, tmp / 2});ans.push_back(node{son[y][0], son[y][1], -tmp / 2});dfs1(y, x);} else {for (auto y : G[x]) {if(y.first == fa) continue;LL tmp = y.second - add[y.first];int tmp1;if(cnt == 0) tmp1 = 1;else tmp1 = 0;ans.push_back((node){son[x][cnt], root, tmp / 2});ans.push_back((node){son[x][cnt], son[x][tmp1], tmp / 2});ans.push_back(node{root, son[x][tmp1], -tmp / 2});update(son[x][cnt], x, tmp);dfs1(y.first, x);cnt++;}}
}int main() {int n;int x, y, z;scanf("%d", &n);for (int i = 1; i < n; i++) {scanf("%d%d%d", &x, &y, &z);adde(x, y, z);}for (int i = 1; i <= n; i++) {if(G[i].size() == 2) {printf("NO\n");return 0;}}for (int i = 1; i <= n; i++) {if(G[i].size() == 1) {root = i;break;}}dfs(root, -1);dfs1(root, -1);printf("YES\n");printf("%d\n", ans.size());for (int i = 0; i < ans.size(); i++) {printf("%d %d %lld\n", ans[i].x, ans[i].y, ans[i].z);}
}

第二种用了类似树剖中重儿子的思想,我们给一颗子树中决定一个优先级最高的叶子结点,这样加的操作是这个叶子结点到它的祖先的路径上进行的,其它的路径没有影响,这样累加影响的时候,如果这个叶子结点,把前面的影响累加上,否则不加。复杂度O(n)。

代码:

#include <bits/stdc++.h>
#define pii pair<int, int>
#define LL long long
using namespace std;
const int maxn = 1010;
vector<pii> G[maxn];
vector<int> son[maxn];
LL add[maxn];
struct node {int x, y;LL z;
};
vector<node> ans;
int root = 1; 
int v[maxn];
void adde(int x, int y, int z) {G[x].push_back(make_pair(y, z));G[y].push_back(make_pair(x, z));
}int dfs(int x, int fa) {for (auto y : G[x]) {if(y.first== fa) continue;int tmp = dfs(y.first, x);son[x].push_back(tmp);}if(G[x].size() == 1) {v[x] = x;return x;}v[x] = son[x][0];return son[x][0];
}void dfs1(int x, int fa, int tot) {int cnt = 0;if(x == root) {int y = G[x][0].first;if(G[y].size() == 1) {ans.push_back((node){x, y, G[x][0].second});return;}LL tmp = G[x][0].second;ans.push_back((node){son[y][0], root, tmp / 2});ans.push_back((node){son[y][1], root, tmp / 2});ans.push_back(node{son[y][0], son[y][1], -tmp / 2});dfs1(y, x, 0);} else {for (auto y : G[x]) {if(y.first == fa) continue;LL tmp = y.second;if(v[y.first] == v[x]) tmp -= tot;int tmp1;if(cnt == 0) tmp1 = 1;else tmp1 = 0;ans.push_back((node){son[x][cnt], root, tmp / 2});ans.push_back((node){son[x][cnt], son[x][tmp1], tmp / 2});ans.push_back(node{root, son[x][tmp1], -tmp / 2});dfs1(y.first, x, y.second);cnt++;}}
}int main() {int n;int x, y, z;scanf("%d", &n);for (int i = 1; i < n; i++) {scanf("%d%d%d", &x, &y, &z);adde(x, y, z);}for (int i = 1; i <= n; i++) {if(G[i].size() == 2) {printf("NO\n");return 0;}}for (int i = 1; i <= n; i++) {if(G[i].size() == 1) {root = i;break;}}dfs(root, -1);dfs1(root, -1, 0);printf("YES\n");printf("%d\n", ans.size());for (int i = 0; i < ans.size(); i++) {printf("%d %d %lld\n", ans[i].x, ans[i].y, ans[i].z);}
}

两份代码中为了实现方便,都找了一个度为1的点为根。

 

转载于:https://www.cnblogs.com/pkgunboat/p/11145961.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/263600.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

iOS- 关于AVAudioSession的使用——后台播放音乐

1.前言   •AVAudioSession是一个单例&#xff0c;无需实例化即可直接使用。AVAudioSession在各种音频环境中起着非常重要的作用•针对不同的音频应用场景&#xff0c;需要设置不同的音频会话分类1.1AVAudioSession的类别   •AVAudioSessionCategoryAmbient–混音播放&…

检索

【摘抄】基于线性表的检索一、检索的基本概念和算法分类1、检索概念&#xff1a; 可以形式化地定义基于关键码的检索。假定k1、k2…kn是互不相同的关键码值&#xff0c;有一个包含n条记录的集合C&#xff0c;形式如下&#xff1a; (k1, R1)&#xff0c;(k2, R2)&#xff0c;…

ajax请求后无法实现指定页面跳转或带参数跳转

问题&#xff1a;我们通过Ajax在前端对Controller的接口进行请求&#xff0c;处理完成后&#xff0c;无法通过Controller的return方法返回指定的页面。 原因&#xff1a;ajax只是局部刷新&#xff0c;所以不能在后台接口直接进行页面的跳转&#xff0c;我们可以在ajax的succes…

例说C#深拷贝与浅拷贝

一开始&#xff0c;先对C#深拷贝与浅拷贝知识做个简单的总结。 无论是浅拷贝与深拷贝&#xff0c;C#都将源对象中的所有字段复制到新的对象中。不过&#xff0c;对于值类型字段&#xff0c;引用类型字段以及字符串类型字段的处理&#xff0c;两种拷贝方式存在一定的区别&#x…

c++程序的多文件组织

当程序规模变大后&#xff0c;一个程序用多个文件组织&#xff0c;便于组织生产。这样&#xff0c;不必每次都重复对所有代码进行编译&#xff0c;而只需编译一次即可。把编译后所形成的目标文件保存起来&#xff0c;以后在需要时把它调出来直接与程序的目标文件相连接即可。 C…

strconv---用来基本类型之间的转换

strconv---用来基本类型之间的转换字符串转int&#xff1a;Atoi(s string)(i int,err error)int转字符串: Itoa(i int)stringstring转换为对应TP类型&#xff1a;ParseBool()、ParseFloat()、ParseInt()、ParseUint()。因为string转其它类型可能会失败&#xff0c;所以这些函数…

企业架构 - 开篇:TOGAF介绍

在《年度总结和计划&#xff1a;去年4个1&#xff0c;今年5个1》中说过今年我准备在项目组引入一个架构方TOGAF。工业和信息化部副部长杨学山在一次内部座谈时提到&#xff1a;与西方发达国家比&#xff0c;国内的信息化建设在硬件方面已经不相上下&#xff0c;在软件方面有5年…

Linux操作系统定时任务系统 Cron

/sbin/service crond start //启动服务 /sbin/service crond stop //关闭服务 /sbin/service crond restart //重启服务 /sbin/service crond reload //重新载入配置 你也可以将这个服务在系统启动的时候自动启动: 在/etc/rc.d/rc.local这个脚本的末尾加上: /sbin/service cron…

C#(4) implicit explicit

最近几节课学的知识点的量有很大增长&#xff0c;加上上机和托福考试的临近&#xff0c;这里练习的所有代码就不走形式全贴出来了&#xff0c;找我自己觉得又不熟悉的点贴出来&#xff0c;争取简明扼要&#xff0c;恩恩 这次主要看接口的问题&#xff1a; 接口可以多继承&#…

什么是SNAT、DNAT?

什么是SNAT、DNAT&#xff1f;SNAT 企业内部的主机A想访问互联网上的主机C&#xff0c;首先将请求数据包&#xff08;源&#xff1a;ipA&#xff0c;目标&#xff1a;ipC&#xff09;发送到防火墙所在主机B&#xff0c;B收到后将数据包源地址改为本机公网网卡的ip&#xff08;源…

ASP.NET读取(导入)CSV文件[献给菜鸟的我们]

CSV文件本身是TXT文件。 所以..可以通过FileStream文件流的方式读取. 如下代码: public void GetCSV1() { FileStream fs new FileStream("D:\\ReportLowIDAndHighID.csv", FileMode.Open, FileAccess.Read); //FileStream fs new FileStream(&…

【jquery】基于 jquery 实现 ie 浏览器兼容 placeholder 效果

placeholder 是 html5 新增加的属性&#xff0c;主要提供一种提示&#xff08;hint&#xff09;&#xff0c;用于描述输入域所期待的值。该提示会在输入字段为空时显示&#xff0c;并会在字段获得焦点时消失。placeholder 属性适用于以下类型的 input 标签&#xff1a;text, se…

连接远程电脑中的虚拟机---端口映射

连接远程电脑中的虚拟机---端口映射问题:A主机中运行有2台虚拟机&#xff0c;现在我们希望在B主机中通过ssh&#xff08;或其他方式&#xff09;访问A主机中的2台虚拟机。(前提&#xff1a;B主机可以ping通A主机&#xff0c;即A有公网IP或A、B在同一子网下) 解决方法 设置虚拟…

Unity 动画属性

在动画的使用上使用不当的设置往往会造成不可预料的结果。 首先&#xff0c;如果动画自身可以驱动物体移动&#xff0c;那么在Animator组件上必须选择apply root motion&#xff0c;物体的动画位移才能生效&#xff0c;否则动画只能在原地播放。 第二&#xff0c;Bake Into Pos…

获取Dataset前几条数据的两种方法

第一种 public static DataView GetLatestComments(int numComments) { DataView Comments new DataView(GetComments()); Comments.Sort “DateCreated Desc“; string filter string.Empty; string delimiter string.Empty; numComments Math.Min(numComments, Comm…

Javascript正则匹配数字,中英文,中横线,下划线,utf-8中文

为什么80%的码农都做不了架构师&#xff1f;>>> function check_string(nickname) {var reg /^[A-Za-z0-9-_\u4e00-\u9fa5]{4,30}$/;if (!reg.test(nickname)) {return false;}return true; } 转载于:https://my.oschina.net/biezhi/blog/396989

解决<style>无法重写.css文件的问题

解决style无法重写.css文件的问题问题&#xff1a;在main.css已经定义了.main_content {width: 10px;}。然而现在在index.html中&#xff0c;我们希望main_content的宽度设置为20px。 解决思路&#xff1a;在index.html中加入如下定义后&#xff0c;我们会发现格式依旧为10px&…

Unity3D 旋转

Unity有两种设置物体旋转的方式&#xff0c;一种时用Rotate&#xff08;&#xff09;函数来旋转&#xff0c;另一种时直接构造目标Quaternion来直接赋予rotation。 好吧&#xff0c;不知到写什么&#xff0c;各种旋转和unity2D差不多。在国内网站基本都是写入门的结果&#xff…

基于linux的集群系统LVS

一 LVS &#xff08;Linux Virtual Server&#xff09;针对高可伸缩、高可用网络服务的需求&#xff0c;我们给出了基于IP层和基于内容请求分发的负载平衡调度解决方法&#xff0c;并在Linux内核中实现了这些方法&#xff0c;将一组服务器构成一个实现可伸缩的、高可用网络服务…

java下包内继承时编译不过解决方案

代码源自《java核心技术一卷》抽象表示如下&#xff1a;ManagerTest.javapackage inheritance;...public class ManagerTest{}存放于&#xff1a;inheritance/ManagerTest.javaManager.javapackage inheritance;...public class Manager{}存放于&#xff1a;inheritance/Manage…