[Luogu P1268] 树的重量 (巧妙的构造题)
题面
传送门:https://www.luogu.org/problemnew/show/P1268



Solution
这是一道极其巧妙的构造题
先做一个约定[i,j]表示从i到j的距离
我们可以先从n=2,也就是最简单的情况来切入这道题
对于n=2,答案显然是[1,2]

接下来考虑n=3
如下图所示
这棵树一定是长成这样的

也就是说三这个节点一定是插在1与2两个节点之间的
我们可以发现,3节点的插入使得树的权值增加了([1,3]+[2,3]-[1,2])/2 (即紫线与蓝线的权值和减去绿线除以二)
我们可以把这个权值贡献的式子推广到一般情况
即x节点插入在[i,j]路径上
其对答案的贡献为([i,x]+[j,x]-[i,j])/2
接下来,我们继续把之前的结论推广到一般情况

四号节点接下来是不是有可能加入在[1,2],[1,3],[2,3]这三条路径中
答案要求整棵树权值和尽可能小,我们只需要在三种情况中选最小值就好
我想你已经找到了一个O(n^3)的算法
就是枚举3~n的插入点,再用两层循环枚举所插入的边
复杂度O(n^3)
事实上,我们已经可以过这道题了.
但我们的复杂度还可以更优
重新再看一下这张图

是不是可以发现我们紫色的那个其实是重复枚举
因为[1,4]+[3,4]-[1,3] 和[2,4]+[3,4]-[2,3] 其实都是一毛一样的!!!
这个结论也可以推广至一般状况中
所以说我们完全可以省去枚举中的一维
只枚举1~n就好
时间复杂度O(n^2)
Code
//Luogu P1268 树的重量
//May,30th,2018
//构造妙题
#include<iostream>
#include<cstdio>
using namespace std;
long long read()
{
long long x=0,f=1; char c=getchar();
while(!isdigit(c)){if(c=='-') f=-1;c=getchar();}
while(isdigit(c)){x=x*10+c-'0';c=getchar();}
return x*f;
}
const int N=30+5;
int n,a[N][N];
int main()
{
while(1)
{
memset(a,0,sizeof a);
int ans=0;
n=read();
if(n==0) break;
for(int i=1;i<n;i++)
for(int j=i+1;j<=n;j++)
a[i][j]=a[j][i]=read(); ans+=a[1][2];
for(int i=3;i<=n;i++)
{
int t_ans=0x3f3f3f3f;
for(int j=1;j<i;j++)
for(int k=1;k<j;k++)
t_ans=min(t_ans,(a[j][i]+a[k][i]-a[j][k])/2);
ans+=t_ans;
}
printf("%d\n",ans);
}
return 0;
}
正解(三方)(C++)
//Luogu P1268 树的重量
//May,30th,2018
//构造妙题
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
long long read()
{
long long x=0,f=1; char c=getchar();
while(!isdigit(c)){if(c=='-') f=-1;c=getchar();}
while(isdigit(c)){x=x*10+c-'0';c=getchar();}
return x*f;
}
const int N=30+5;
int n,a[N][N];
int main()
{
while(1)
{
memset(a,0,sizeof a);
int ans=0;
n=read();
if(n==0) break;
for(int i=1;i<n;i++)
for(int j=i+1;j<=n;j++)
a[i][j]=a[j][i]=read(); ans+=a[1][2];
for(int i=3;i<=n;i++)
{
int t_ans=0x3f3f3f3f;
for(int j=1;j<i;j++)
t_ans=min(t_ans,(a[j][i]+a[1][i]-a[j][1])/2);
ans+=t_ans;
}
printf("%d\n",ans);
}
return 0;
}
正解(平方)(C++)
[Luogu P1268] 树的重量 (巧妙的构造题)的更多相关文章
- luogu p1268 树的重量——构造,真正考验编程能力
题目链接:http://www.luogu.org/problem/show?pid=1268#sub -------- 这道题费了我不少心思= =其实思路和标称毫无差别,但是由于不习惯ACM风格的题 ...
- 【luogu P1268 树的重量】 题解
题目链接:https://www.luogu.org/problemnew/show/P1268 给定所有点间的最短路求原图所有路径和 形如: 我们需要计算红边+绿边 绿边 = (红边+蓝边+紫边)/ ...
- luogu P1268 树的重量
一开始把这题想复杂了,,, 这里记\(di[i][j]\)表示\(i\)到\(j\)的距离 首先如果\(n=2\),答案显然为\(di[1][2]\) 如果\(n=3\) 懒得画图了盗图过来 那么3号 ...
- 洛谷—— P1268 树的重量
P1268 树的重量 构造类题目,看不出个所以然来... emmm,只好看题解: 只有两个点,那一条路径就是$ans$ 考虑三个点,那么$3$这个点相对于树上的路径(已经加入树上的边的距离) 为:$( ...
- 洛谷P1268 树的重量
P1268 树的重量 85通过 141提交 题目提供者该用户不存在 标签树形结构 难度提高+/省选- 提交该题 讨论 题解 记录 最新讨论 有这种情况吗!!!! 题意似乎有问题 题目描述 树可以用来表 ...
- 洛谷 P1268 树的重量 解题报告
P1268 树的重量 题目描述 树可以用来表示物种之间的进化关系.一棵"进化树"是一个带边权的树,其叶节点表示一个物种,两个叶节点之间的距离表示两个物种的差异.现在,一个重要的问题 ...
- 洛谷P1268 树的重量 【构造 + 枚举】
题目描述 树可以用来表示物种之间的进化关系.一棵"进化树"是一个带边权的树,其叶节点表示一个物种,两个叶节点之间的距离表示两个物种的差异.现在,一个重要的问题是,根据物种之间的距离 ...
- P1268 树的重量【构造】
题目描述 树可以用来表示物种之间的进化关系.一棵“进化树”是一个带边权的树,其叶节点表示一个物种,两个叶节点之间的距离表示两个物种的差异.现在,一个重要的问题是,根据物种之间的距离,重构相应的“进化树 ...
- P1268 树的重量
题目描述 树可以用来表示物种之间的进化关系.一棵“进化树”是一个带边权的树,其叶节点表示一个物种,两个叶节点之间的距离表示两个物种的差异.现在,一个重要的问题是,根据物种之间的距离,重构相应的“进化树 ...
随机推荐
- Spring基础知识1--环境搭建、bean创建、依赖注入、注解注入
一.Spring两大核心内容 1.控制反转IOC/DI: 应用本身不负责对象的创建和维护,对象和依赖对象的创建完全交给容器管理. 2.AOP(面向切面编程):通过预编译的方式,在运行期通过动态代理的 ...
- Leetcode PHP题解--D125 107. Binary Tree Level Order Traversal II
val = $value; } * } */ class Solution { private $vals = []; /** * @param TreeNode $root * @return In ...
- 剑指Offer(一):二维数组中的查找
一.前言 刷题平台:牛客网 二.题目 在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整 ...
- 【题解】[CH弱省胡策R2]TATT
本蒟蒻第一道\(K-D-Tree\)维护\(dp\) Question 题目大意:求一条路径,使得其四个维度单调不降. 先排序消掉一维再说. 对于每一个点,初始的时候绝对长度是1啊.于是,先赋值一个1 ...
- 一文搞懂PV、UV、VV、IP及其关系与计算
写在前面 十一长假基本上过去了,很多小伙伴在假期当中还是保持着持续学习的心态,也有不少小伙伴在微信上问我,让我推送相关的文章.这个时候,我都是抽空来整理小伙伴们的问题,然后,按照顺序进行推文. PS: ...
- 加快ASP。NET Core WEB API应用程序。第2部分
下载source from GitHub 使用各种方法来增加ASP.NET Core WEB API应用程序的生产力 介绍 第1部分.创建测试RESTful WEB API应用程序第2部分.增加了AS ...
- Go 并发操作
goroutine 在其他的编程语言中,线程调度是交由os来进行处理的. 但是在Go语言中,会对此做一层封装,Go语言中的并发由goroutine来实现,它类似于用户态的线程,更类似于其他语言中的协程 ...
- Redis的介绍以及安装
redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库,缓存和消息中间件 高速缓存介绍 高速缓存利用内存保存数据,读写速度远超硬盘 高速缓存可以减少 I/O 操作,降 ...
- 请求https接口时报错:Caused by SSLError(SSLError(1, u'[SSL: CERTIFICATE_VERIFY_FAILED] certificat,安装certifi
如何解决SSL 根证书验错误: 一种解决方法是:verify=False 在session.request 里面: session.post(post_url,data=post_data,heade ...
- linux(centos8):用tr替换或删除字符
一,tr命令的用途 tr命令可以替换或删除文件中的字符 它从标准输入设备读取数据, 处理完成将结果输出到标准输出设备 说明:刘宏缔的架构森林是一个专注架构的博客,地址:https://www.cnbl ...