APIO2010巡逻(树上带权直径)
题目链接:https://www.luogu.org/problem/show?pid=3629
题解:
看到这题题解一片空白,身为蒟蒻的我也想为社会做点贡献……
首先要知道:
1.假如不加边,每条边都要走两次。
2.假如加了一条边,那么会形成一个环,而且环上的边只需要走一次,其余的边要走两次。
(自己yy以下就可以知道了)
对于k=1的话,我们就要使环上的边尽量多,也就是说我们要找树的直径,使得树的直径在环内。
而对于k=2的话,再加一条边的时候,会再多一个环。
这时我们要知道:
1.如果一条边仅在第二个环出现过,只用走一次。
2.如果一条边在两个环都出现过,要走两次。
3.如果一条边在两个环都没出现过,要走两次。
(自己yy以下就可以知道了)
所以我们给第一个环上的边-1的权值,其余边给1的权值,求出树上权值最大的一条路径(假直径O(∩_∩)O)
然后问题就迎刃而解了。
附上蒟蒻的代码,我的100来行,同一机房神犇的代码60+行
#include<iostream> #include<fstream> #include<algorithm> #include<cstdio> #include<cmath> #include<cstdlib> #include<cstring> using namespace std; int n,k,root1,root2,cir,cir2; int cur,head[100010],d[100010],heavy[100010],w[100010]; struct tedge {int to,nex; }e[200010]; struct data {int e,v; }son[100010]; void Add(int u,int v) {cur++;e[cur].to = v;e[cur].nex = head[u];head[u] = cur; } bool cmp(data a,data b) {return a.e>b.e; } void dfs(int u,int f) {int cnts=0;for (int i=head[u]; i!=-1; i=e[i].nex){int v=e[i].to;if (v==f) continue;dfs(v,u);if (d[u]<d[v]+w[v]) {d[u] = d[v]+w[v];heavy[u] = v;}}for (int i=head[u]; i!=-1; i=e[i].nex){int v=e[i].to;if (v==f) continue;cnts++; son[cnts].e = d[v]+w[v]; son[cnts].v = v;}sort(son+1,son+1+cnts,cmp);if (cnts==0) d[u] = 0;if (cnts>=1&&cir<son[1].e) {cir = son[1].e;root1 = son[1].v;}if (cnts>=2&&cir<son[1].e+son[2].e){cir = son[1].e+son[2].e;root1 = son[1].v; root2 = son[2].v;} } void Change() {int u = root1;while (u!=0){w[u] = -1; u = heavy[u];}u = root2;while (u!=0){w[u] = -1; u = heavy[u];} } int main() {scanf("%d%d",&n,&k);for (int i=0; i<=n; i++)head[i] = -1;for (int i=2; i<=n; i++)w[i] = 1;for (int i=1; i<n; i++){int x,y;scanf("%d%d",&x,&y);Add(x,y); Add(y,x);}cir = 0;dfs(1,0);if (k==1){printf("%d\n",2*(n-1)-cir+1);return 0;}Change();cir2 = cir; cir = -1e9;for (int i=1; i<=n; i++)d[i] = -1e9;dfs(1,0);printf("%d\n",2*(n-1)-cir-cir2+2);return 0; }
转载于:https://www.cnblogs.com/Janous/p/7526024.html
APIO2010巡逻(树上带权直径)相关推荐
- 【树的直径】解题报告: luogu P3629 [APIO2010]巡逻(树的直径,位运算成对变换,思维)
题目链接:P3629 [APIO2010]巡逻 首先看题,从1号结点开始,全部遍历并回到1号结点会恰好经过所有的边两次,这样总长度为 2∗(n−1)2*(n-1)2∗(n−1). 那么如果建立一条路以 ...
- LibreOJ #2478.「九省联考 2018」林克卡特树 树形dp+带权二分
题意 给出一棵n个节点的树和k,边有边权,要求先从树中选k条边,然后把这k条边删掉,再加入k条边权为0的边,满足操作完后的图仍然是一棵树.问新树的带权直径最大是多少. n,k≤3∗105n,k≤3∗1 ...
- 2017 西安网络赛A Tree(树上静态查询,带权并查集,矩阵乘法压位,好题)
题目链接 题意: 给出 \(n(n \leq 3000)\) 个结点的一棵树,树上每个结点有一个 \(64 \times 64\) 的 \(0,1\)矩阵,每个结点上的矩阵是根据输入的 \(seed\ ...
- 洛谷.4383.[八省联考2018]林克卡特树lct(树形DP 带权二分)
题目链接 \(Description\) 给定一棵边带权的树.求删掉K条边.再连上K条权为0的边后,新树的最大直径. \(n,K\leq3\times10^5\). \(Solution\) 题目可以 ...
- 【ZJOI2015】幻想乡战略游戏【点分树】【带权重心】
题意:nnn个点带边权的树,动态修改点权viv_ivi,最小化 钦定一个点xxx 后 ∑idist(x,i)∗vi\sum\limits_{i} dist(x,i)*v_ii∑dist(x,i)∗ ...
- java带权连通图上最小权边,连通图最小生成树的算法及实现
连通图的最小生成树 生成树定义: 无向连通图G的极小连通子图,称为它的生成树.(n个顶点,n-1条边) 考虑一下下面这个图 上图是一个完全图,它的生成树不是唯一的,我们列出最特殊的两种情况 上面2个图 ...
- 树形结构 —— 并查集 —— 带权并查集
[概述] 定义:带权并查集即是结点存有权值信息的并查集. 适用:当两个元素之间的关系可以量化,并且关系可以合并时,可以使用带权并查集来维护元素之间的关系. 权值:带权并查集每个元素的权通常描述其与并查 ...
- P4383 [八省联考2018]林克卡特树lct 树形DP+凸优化/带权二分
$ \color{#0066ff}{ 题目描述 }$ 小L 最近沉迷于塞尔达传说:荒野之息(The Legend of Zelda: Breath of The Wild)无法自拔,他尤其喜欢游戏中的 ...
- 基于C++的带权无向图的实现 (三)- Prim最小生成树算法
该系列文章是本人整理的有关带权无向图的数据结构和算法的分析与实现,若要查看源码可以访问我的github仓库,如有问题或者建议欢迎各位指出. 目录 基于C++的带权无向图的实现 (一)- 数据结构 基于 ...
最新文章
- 查找字符位置_Excel中查找字符第N次出现的位置信息,换个思路其实很简单
- 解压RK3288的boot.img修改init.rc 添加开机自启动脚本
- Android Framework增加API 报错 Missing nullability on parameter
- git安装和初步使用
- 刷卡提示57能恢复吗_硬盘格式化之后数据还能恢复吗?
- docker网络--理解linux底层实现机制、docker网络模式
- QTcrateor 编译 ROS
- Kruskal算法 最小生成树
- nrm : 无法加载文件 E:\node\node_global\nrm.ps1,因为在此系统上禁止运行脚本
- @ResponseBody与@RestController的作用与区别
- [Android] 开发一款软件我学到了些什么?
- 一文搞懂深度学习中常用的优化算法
- android在体检报告叫什么,体检报告检测分析app
- 集合框架ArrayList 源码分析(二)
- 如何在简历中使用STAR法则
- TCTF writeup
- 微信网站被误封,不知道为何被封,站长认证一直失败该如何解决?
- google map的简单应用-显示华南理工大学
- 蓝桥杯单片机比赛学习:6、中断系统之定时器中断的基本原理
- 2060年软件工程师会像电报报务员那样过时?