luogu 4886
点分治好题
统计距离正常点分治统计即可,我们只需考虑何时达到最优
有两种情况:
第一:代价最大的询问两个端点在不同的两个子树中
因为这种情况下,无论根向那个子树移动都会等价地增加到达另一个端点的代价,因此此时总代价已经达到最小
第二:代价最大的询问有多组,且这些点不在同一棵子树中
同情况一,如果我们把根偏向其中某一棵子树移动的话,那么一定会等价地增大另一端的代价,因此总代价已经达到最小
这样的话直接统计就好了
贴代码:
#include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <queue>
#include <stack>
using namespace std;
struct Edge
{
int nxt;
int to;
int val;
}edge[200005];
int q[100005][2];
int siz[100005];
int rt,s;
int head[100005];
int maxp[100005];
int ans=0x3f3f3f3f;
bool vis[100005];
int dis[100005];
int bel[100005];
int ccl[100005];
int col=0,typ=0;
int cnt=1,maxx=0;
int n,m;
void add(int l,int r,int w)
{
edge[cnt].nxt=head[l];
edge[cnt].to=r;
edge[cnt].val=w;
head[l]=cnt++;
}
void get_rt(int x,int fx)
{
siz[x]=1,maxp[x]=0;
for(int i=head[x];i;i=edge[i].nxt)
{
int to=edge[i].to;
if(to==fx||vis[to])continue;
get_rt(to,x);
siz[x]+=siz[to];
maxp[x]=max(maxp[x],siz[to]);
}
maxp[x]=max(maxp[x],s-siz[x]);
if(maxp[x]<maxp[rt])rt=x;
}
void dfs(int x,int fx,int dep)
{
dis[x]=dep;
if(!fx)bel[x]=0;
for(int i=head[x];i;i=edge[i].nxt)
{
int to=edge[i].to;
if(to==fx)continue;
if(!fx)col++;
bel[to]=col;
dfs(to,x,dep+edge[i].val);
}
}
int calc(int x)
{
dis[x]=maxx=0,dfs(x,0,0);
typ++;
for(int i=1;i<=m;i++)
{
ccl[i]=0;
if(dis[q[i][0]]+dis[q[i][1]]>maxx)maxx=dis[q[i][0]]+dis[q[i][1]],ccl[i]=++typ;
else if(dis[q[i][0]]+dis[q[i][1]]==maxx)ccl[i]=typ;
}
return typ;
}
void solve(int x)
{
vis[x]=1;
int k=calc(x);
int ori=0;
for(int i=1;i<=m;i++)
{
if((bel[q[i][0]]!=bel[q[i][1]])&&ccl[i]==k){ori=-1;break;}
else if(ccl[i]==k&&!ori)ori=bel[q[i][0]];
else if(ccl[i]==k)if(bel[q[i][0]]!=ori){ori=-1;break;}
}
ans=min(ans,maxx);
for(int i=head[x];i;i=edge[i].nxt)
{
int to=edge[i].to;
if(vis[to])continue;
if(bel[to]==ori)rt=0,s=siz[to],get_rt(to,x),solve(rt);
}
}
inline int read()
{
int f=1,x=0;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int main()
{
n=read(),m=read();
for(int i=1;i<n;i++)
{
int x=read(),y=read(),z=read();
add(x,y,z),add(y,x,z);
}
maxp[0]=0x3f3f3f3f;
for(int i=1;i<=m;i++)q[i][0]=read(),q[i][1]=read();
rt=0,s=n,get_rt(1,0),solve(rt);
printf("%d\n",ans);
return 0;
}
luogu 4886的更多相关文章
- [luogu 4886] 快递员
传送门 Solution 虽然不是点分治但用类似点分治的方法不断接近正确结果 Code // luogu-judger-enable-o2 #include <cstdio> #inclu ...
- Luogu 魔法学院杯-第二弹(萌新的第一法blog)
虽然有点久远 还是放一下吧. 传送门:https://www.luogu.org/contest/show?tid=754 第一题 沉迷游戏,伤感情 #include <queue> ...
- luogu p1268 树的重量——构造,真正考验编程能力
题目链接:http://www.luogu.org/problem/show?pid=1268#sub -------- 这道题费了我不少心思= =其实思路和标称毫无差别,但是由于不习惯ACM风格的题 ...
- [luogu P2170] 选学霸(并查集+dp)
题目传送门:https://www.luogu.org/problem/show?pid=2170 题目描述 老师想从N名学生中选M人当学霸,但有K对人实力相当,如果实力相当的人中,一部分被选上,另一 ...
- [luogu P2647] 最大收益(贪心+dp)
题目传送门:https://www.luogu.org/problem/show?pid=2647 题目描述 现在你面前有n个物品,编号分别为1,2,3,--,n.你可以在这当中任意选择任意多个物品. ...
- Luogu 考前模拟Round. 1
A.情书 题目:http://www.luogu.org/problem/show?pid=2264 赛中:sb题,直接暴力匹配就行了,注意一下读入和最后一句话的分句 赛后:卧槽 怎么只有40 B.小 ...
- luogu P2580 于是他错误的点名开始了
luogu P2580 于是他错误的点名开始了 https://www.luogu.org/problem/show?pid=2580 题目背景 XS中学化学竞赛组教练是一个酷爱炉石的人. 他会一边 ...
- CJOJ 1331 【HNOI2011】数学作业 / Luogu 3216 【HNOI2011】数学作业 / HYSBZ 2326 数学作业(递推,矩阵)
CJOJ 1331 [HNOI2011]数学作业 / Luogu 3216 [HNOI2011]数学作业 / HYSBZ 2326 数学作业(递推,矩阵) Description 小 C 数学成绩优异 ...
- Luogu 1349 广义斐波那契数列(递推,矩阵,快速幂)
Luogu 1349 广义斐波那契数列(递推,矩阵,快速幂) Description 广义的斐波那契数列是指形如\[A_n=p*a_{n-1}+q*a_{n-2}\]的数列.今给定数列的两系数p和q, ...
- Luogu 1962 斐波那契数列(矩阵,递推)
Luogu 1962 斐波那契数列(矩阵,递推) Description 大家都知道,斐波那契数列是满足如下性质的一个数列: f(1) = 1 f(2) = 1 f(n) = f(n-1) + f(n ...
随机推荐
- [Notes-DS-2]线性结构
分割线------------- 分割线----------------
- Kubernetes-Pod进阶
目录: 资源限制 CPU资源单位 内存资源单位 重启策略 健康检查/探针 探针的三种规则 Probe支持三种检查方法 总结 Pod 进阶 资源限制 当定义 Pod 时可以选择性地为每个容器设定所需要的 ...
- vue资料链接
vue 官方api:https://cn.vuejs.org/ vue资源精选:http://vue.awesometiny.com/ vue GitHub地址:https://github.com/ ...
- ubuntu常用操作
Ubuntu22.04 server 创建随操作系统自动启动: 创建rc-local.service cp /lib/systemd/system/rc.-local.service /etc/sys ...
- 【java数据结构与算法】选择排序
选择排序原理剖析: 假设数组arr使用选择排序 每一轮选出数组最小的元素 arr.lenth个元素,只需要找出arr.length-1个元素的正确位置 选择排序便进行结束 外层for循环控制选择排序的 ...
- [转并修改]C#编程中跨线程访问控件
C#编程中跨线程访问控件 一.简述 二.Winforms中跨线程访问控件 三.WPF中跨线程访问控件 参考文档 一.简述 C#中不允许跨线程直接访问界面控件,即一个线程中如主线程创建的控件不允许被其他 ...
- selenium grid4.0+分布式的部署配置(hub/node方式)
一.grid安装 本文已jar包的方式讲解,访问并下载jar包:Releases · SeleniumHQ/selenium · GitHub 二.grid配置 假设主机:10.1.5.219,从机: ...
- [部署日记]Android Studio在安装完后,sdk依旧提示SDK emulator directory is missing
问题起源: 今天在闲着没事搞了个go的rest-api,用postman测试了一下可行,于是一拍大腿决定写一个安卓手机程序,于是一拍大腿重新下载了卸载没多久因为没空间放原神的Android Studi ...
- 【Java学习Day11】变量种类及命名规范
变量 变量是什么:就是可以变化的量 Java是一种强类型语言,每个变量都必须声明其类型 Java变量是程序中最基本的存储单元,其要素包括变量名,变量类型和作用域 type varName [=valu ...
- 从main_phase跳回reset_phase的方式
在main_phase中调用: phase.jump(uvm_reset_phase::get()); 注意需要防止进入死循环.