直径上的乱搞一般要求出这条直径上的点集或者边集

bzoj1999:对直径上的点集进行操作

/*
给出一颗树,在树的直径上截取长度不超过s的路径
定义点u到s的距离为u到s的最短路径长度
定义s的偏心距为所有点到s的最大距离
定义树网的核为偏心距最小的s
给定s,请求出最小偏心距 题目中的结论:树的直径不唯一,但所有直径必定相交于直径的中点
推论:任意直径上求出的最小偏心距都相等
将树转化成另一个模型:即所有直径以外的分支都挂载在直径左右侧,
提取出直径,设直径上的结点u1,u2,u3...ut
那么用i,j两个指针,i从u1开始,j一直在直径上右移直到uj距离ui不超过s,
用单调队列维护在挂载在区间[i,j]的最大分支长度,那么这一段区间对应的偏心距就是
max(max{d(uk)},dist(u1,ui),dist(uj,ut)) ,k在区间[i,j]内
d数组是uk挂载的分支最大深度
由于没有负权,可以用dfs跑两遍求出直径,并用pre数组将直径记录下来
然后从每个直径上的点出发再进行一次dfs求出这个直径上挂载的分支的深度
然后用单调队列维护结果即可
*/
#include<bits/stdc++.h>
using namespace std;
#define maxn 500005
struct Edge{int to,nxt,w;}edge[maxn<<];
int head[maxn],tot,n,s;
void init(){
memset(head,-,sizeof head);
tot=;
}
void addedge(int u,int v,int w){
edge[tot].nxt=head[u];edge[tot].to=v;edge[tot].w=w;
head[u]=tot++;
}
int dep[maxn],fa[maxn],is[maxn],dis[maxn];
void dfs(int u,int pre,int deep){//返回深度最大的点
dep[u]=deep;fa[u]=pre;
for(int i=head[u];i!=-;i=edge[i].nxt){
int v=edge[i].to;
if(v==pre)continue;
dfs(v,u,deep+edge[i].w);
}
}
int dfs2(int u,int pre){//求直径上的点挂载的分支的深度
int res=;
for(int i=head[u];i!=-;i=edge[i].nxt){
int v=edge[i].to;
if(v==pre || is[v])continue;
res=max(dfs2(v,u)+edge[i].w,res);
}
return res;
} int main(){
init();
cin>>n>>s;
for(int i=;i<n;i++){
int u,v,w;cin>>u>>v>>w;
addedge(u,v,w);addedge(v,u,w);
}
//两次dfs求出直径
int S=;dfs(,,);
for(int i=;i<=n;i++)
if(dep[S]<dep[i])S=i;
memset(dep,,sizeof dep);
int T=;dfs(S,,);
for(int i=;i<=n;i++)
if(dep[T]<dep[i])T=i; // cout<<s<<" "<<t<<endl; fa[S]=;
for(int i=T;i;i=fa[i])is[i]=;//标记直径上的点
for(int i=T;i;i=fa[i])dis[i]=dfs2(i,fa[i]);//求出直径上挂载的分支的最大深度 //单调队列
int q[maxn]={},l=,r=,j=T,ans=<<;
q[]=T;
for(int i=T;i;i=fa[i]){
while(fa[j]!= && dep[i]-dep[fa[j]]<=s){//j往上移,把j加入单调队列
j=fa[j];
while(l<=r && dis[q[r]]<=dis[j])r--;
q[++r]=j;
ans=min(ans,max(dis[q[l]],max(dep[j]-dep[S],dep[T]-dep[i])));
}
while(q[l]==i)++l;
} cout<<ans<<endl;
}

bzoj1912 负权树求直径(只能用树形dp),然后记录直径上的边来回溯到两端点,同时将直径上的边权变负

/*
分情况讨论问题
一条边也不加的情况,显然每条边要扫描两次,
该情况的答案是2(n-1)
只加一条边的情况,找到直径,将其变成一个环,在这个环上的所有边只要扫描一次,剩下的边就要扫描两次
设直径为L,该情况下的答案是 2(n-1-L)+L+1=2n-L-1=2(n-1)-(L-1)
加两条边的情况,在加入第一条边出现环的情况下,再加入一条边形成的环会和原来的环有重合
重合的部分任然要扫描两次,所以新加入的边要使形成的环和原来的环非重合的边和重合的边的差最大
那么如何快速求新加入的边?只要将第一条边加入后形成的环的边权值变成-1,然后再求一次直径即可
设第一次的直径L1,第二次的直径L2,那么该情况下的答案是2(n-1)-(L1-1)-(L2-1)
*/
#include<bits/stdc++.h>
using namespace std;
#define maxn 100005
struct Edge{int to,nxt,w;}edge[maxn<<];
int head[maxn],tot,n,k,ans;
void init(){
memset(head,-,sizeof head);
tot=;
}
void addedge(int u,int v){
edge[tot].w=;edge[tot].to=v;edge[tot].nxt=head[u];head[u]=tot++;
} int pre1[maxn],pre2[maxn],dp[maxn],mx;//记录x的最长和次长子链的边的下标
int dfs(int x,int fa)
{
int mx1=,mx2=;
for(int i=head[x];i!=-;i=edge[i].nxt)
if(edge[i].to!=fa)
{
int v=edge[i].w+dfs(edge[i].to,x);
if(v>mx1)mx2=mx1,mx1=v,pre2[x]=pre1[x],pre1[x]=i;
else if(v>mx2)mx2=v,pre2[x]=i;
}
if(mx1+mx2>ans)ans=mx1+mx2,mx=x;
return mx1;
} int main(){
init();
memset(pre1,-,sizeof pre1);
memset(pre2,-,sizeof pre2);
cin>>n>>k;
int tot=*n-;
for(int i=;i<n;i++){
int u,v;cin>>u>>v;
addedge(u,v);addedge(v,u);
}
dfs(,);
tot=tot-ans+;
if(k==)
{
ans=;
for(int i=pre1[mx];i!=-;i=pre1[edge[i].to])edge[i].w=edge[i^].w=-;
for(int i=pre2[mx];i!=-;i=pre1[edge[i].to])edge[i].w=edge[i^].w=-;
dfs(,);tot=tot-ans+;
}
cout<<tot<<endl;
}

最新文章

  1. HDU 1257 最少拦截系统【LIS】
  2. Sharepoint 2010 工作流启动时处理表单出错
  3. 【leetcode❤python】 Maximum Depth of Binary Tree
  4. 禁用gridview默认点击效果
  5. 转:【Spring MVC Controller单例陷阱】
  6. C++编译指令#pragma pack的配对使用
  7. VM虚拟机下CentOS 6.5配置IP地址的三种方法
  8. RFC Transactional RFC (tRFC) queue RFC(qRFC) 概念
  9. Android LayoutInflater解析
  10. postgres-xl 集体搭建(2)
  11. PAGELATCH_x 等待--转载
  12. Sprint 冲刺第三阶段第3-5天
  13. Java高频面试题
  14. python的前后端分离(一):django+原生js实现get请求
  15. linux 查找locate find
  16. Android 如何在Eclipse 引入外部纯Java项目(不是打成Jar使用)
  17. bulk insert 在mssql中使用
  18. set数组去重
  19. 洛谷 P4018 Roy&amp;October之取石子
  20. tomcat控制台启动成功但是却访问不了主页

热门文章

  1. linux 统计某目录文件的行数
  2. openstack Q版部署-----Mysql、MQ、Memcached安装配置(2)
  3. 为什么python运行的慢
  4. MySQL报错总结
  5. Node.js的异步IO和事件轮询
  6. Go语言程序开发初涉
  7. libevent学习笔记 一、基础知识【转】
  8. ios webview调试
  9. mq for aix 清理步骤
  10. ubuntu 精简配置