正题


题目大意

刚开始一棵树,在树中加入k条边(k<=2)使得这些边都得走过的情况下,每个点都到达并回到原点的最少边。


解题思路

首先我们发现如果不加边的话答案是2∗(n−1)2*(n-1)2∗(n−1)。
之后我们考虑k=1k=1k=1的情况,我们找树的直径,然后在两个端点之间加边,这样就可以少跑直径长度-1这么多。设直径长度为disdisdis,答案是2∗(n−1)−dis+12*(n-1)-dis+12∗(n−1)−dis+1。

之后我们考虑k=2k=2k=2的情况。我们发现如果之后再找一条直径和之前的直径没有重边的话答案就是2∗(n−1)−dis−dis2+22*(n-1)-dis-dis2+22∗(n−1)−dis−dis2+2。

有重边怎么办,我们发现如果有重边,那么重边就会多跑一次。所以我们可以把第一次直径上所有边权都变成−1-1−1,我们就可以直接2∗(n−1)−dis−dis2+22*(n-1)-dis-dis2+22∗(n−1)−dis−dis2+2。

根据zyczyczyc的说法,第一次用dfsdfsdfs方便记录路径,第二次有负边权所以得用dpdpdp。

完美解决该题


codecodecode

#include<cstdio>
#include<algorithm>
#include<cstring>
#define N 100010
using namespace std;
int n,k,dis,dis2,ls[N],tot;
int pre[N],last,f[N],p,x,y;
struct node{int to,w,next;
}a[2*N];
void addl(int x,int y,int w)//加边
{a[++tot].to=y;a[tot].w=w;a[tot].next=ls[x];ls[x]=tot;
}
void dfs(int x,int fa,int disr)//第一次求直径
{if(disr>dis) dis=disr,p=x;for(int i=ls[x];i;i=a[i].next)if(a[i].to!=fa)pre[a[i].to]=x,dfs(a[i].to,x,disr+a[i].w);
}
void change(int x,int end)//改变边权
{if(x==end) return;for(int i=ls[x];i;i=a[i].next)if(a[i].to==pre[x]){a[i].w=-1;a[i^1].w=-1;change(a[i].to,end);}
}
void dp(int x,int fa)//第二次求直径
{for(int i=ls[x];i;i=a[i].next)if(a[i].to!=fa){int y=a[i].to;dp(a[i].to,x);dis2=max(dis2,f[x]+f[y]+a[i].w);f[x]=max(f[y]+a[i].w,f[x]);}
}
int main()
{tot=1;scanf("%d%d",&n,&k);for(int i=1;i<n;i++){scanf("%d%d",&x,&y);addl(x,y,1);addl(y,x,1);}dfs(1,0,0);last=p;dis=0;dfs(p,0,0);if(k==1){printf("%d",2*(n-1)-dis+1);return 0;}change(p,last);dp(1,0);printf("%d",2*(n-1)-dis-dis2+2);
}

P3629-[APIO2010]巡逻【树的直径】相关推荐

  1. 【树的直径】解题报告: luogu P3629 [APIO2010]巡逻(树的直径,位运算成对变换,思维)

    题目链接:P3629 [APIO2010]巡逻 首先看题,从1号结点开始,全部遍历并回到1号结点会恰好经过所有的边两次,这样总长度为 2∗(n−1)2*(n-1)2∗(n−1). 那么如果建立一条路以 ...

  2. 树的直径【p3629】[APIO2010]巡逻

    Description 在一个地区中有 n 个村庄,编号为 1, 2, ..., n.有 n – 1 条道路连接着这些村 庄,每条道路刚好连接两个村庄,从任何一个村庄,都可以通过这些道路到达其 他任一 ...

  3. APIO2010巡逻(树上带权直径)

    题目链接:https://www.luogu.org/problem/show?pid=3629 题解: 看到这题题解一片空白,身为蒟蒻的我也想为社会做点贡献-- 首先要知道: 1.假如不加边,每条边 ...

  4. 0x63.图论 - 树的直径与最近公共祖先

    目录 一.树的直径(Diameter) 1.树形DP求树的直径 2.两次BFS/DFS求树的直径 1.POJ 1985.Cow Marathon(DFS求树的直径模板题) 2.AcWing 350. ...

  5. [51nod] 1766树上的最远点对 树的直径 树剖LCA+ST表静态查询

    题意: 给你一棵带权树,q次查询,每次给出两个区间,[l1,r1][l2,r2][l_1,r_1] [l_2,r_2][l1​,r1​][l2​,r2​]从这两个区间中分别选择两个数字,使得这两个点的 ...

  6. 小A与欧拉路(牛客-树的直径)

    题解: 欧拉路:从图中任意一个点开始到图中任意一个点结束的路径,并且图中每条边只通过恰好一次 问你走完这树上所有的点最短路径是什么. 因为树是没有环的,所以你走到叶子结点的时候需要往回走,也就是再走一 ...

  7. luogu P4408 [NOI2003]逃学的小孩(树的直径)

    整理的算法模板合集: ACM模板 看了半天的题原来没有告诉你三个点的坐标,不然直接跑最短路即可.要求最长的时间,所以我们要自己找到三个点,而在树中最长的路径也就是树的直径.那么本题就可以简化为:在一棵 ...

  8. 模板 - 树上问题(树的直径、动态查询树的直径、树的重心)

    整理的算法模板合集: ACM模板 目录 一.树的直径 树形DP 两次DFS / BFS(找到直径的两个端点) 二.动态修改树的边权并求每个时刻的直径(线段树) 三.树的重心 一.树的直径 树的直径满足 ...

  9. [Bzoj2282]消防(二分答案+树的直径)

    Description 某个国家有n个城市,这n个城市中任意两个都连通且有唯一一条路径,每条连通两个城市的道路的长度为zi(zi<=1000). 这个国家的人对火焰有超越宇宙的热情,所以这个国家 ...

最新文章

  1. 70佳精美的PSD素材免费下载(上篇)
  2. 软件开发环境-环境用户界面
  3. 研究生再次大幅扩招!高校能否承载?教育部最新表态来了
  4. spring 源代码地址
  5. 经典设计模式——策略模式
  6. JavaScript立即执行函数学习
  7. 微信朋友圈也可以发语音你们造吗?
  8. 面试官系统精讲Java源码及大厂真题 - 39 经验总结:不同场景,如何使用线程池
  9. Qt-按钮无文本显示
  10. Boss直聘Python爬虫实战
  11. NHibernate3.2+Asp.net MVC3+Extjs 4.0.2项目实践(二): NHibernate数据访问层实现
  12. Recommended Browsers for Oracle E-Business Suite 11i/R12
  13. JavaScript之全局函数详解
  14. ssm框架下开发RESTful json简单实例
  15. javaWeb毕业设计项目完整源码附带论文合集免费下载
  16. Arcgis拓扑检查之面空隙(内附具体操作步骤)
  17. U2000北向 CORBA客户端代码Java编程示例
  18. 【NUC980开发板DIY项目大挑战】串口服务器
  19. mysql jdbc dao_MYSQL 之 JDBC(九):增删改查(七)DAO的补充和重构
  20. python3 基础语法分享

热门文章

  1. linux安装卷管理,Linux安装管理ISCSI卷(initiator端)
  2. java二叉树的深度优先遍历_二叉树的广度优先遍历、深度优先遍历的递归和非递归实现方式...
  3. php return 变量,php内核笔记–函数返回变量return_value
  4. loadrunner录制事件为0_测试工具LoadRunner常见问题汇总,解决方案整理
  5. realloc函_[转载]realloc函数的使用及注意事项(转)
  6. 数据结构 快速排序(详解)
  7. mysql 5.5 免安装_mysql 5.5.56免安装版配置方法
  8. [SpringSecurity]HelloWorld入门案例
  9. [设计模式]迪米特法则
  10. UVA - 839 Not so Mobile