博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Luogu_4886 快递员
阅读量:5235 次
发布时间:2019-06-14

本文共 2623 字,大约阅读时间需要 8 分钟。

一道淀粉质的题目。

先考虑最简单的算法,那便是对每个点都求一边。时间复杂度O(NM)

然后如果我们把每个点的结果对应一个高度,我们会发现。最优解是在这个对应高度形成的三维图像中的谷底(谷缝)

也就数说,对于一条链来说,他是一个开口向上的类似二次函数的一个图形。

具有类似单调性的一类性质。

在O(NM)的算法中,可以使用其剪枝。既是如果相邻的节点的答案要大于当前节点,那么我们就不向那个节点进行搜索。

为什么? 如果相邻节点的答案小于当前点,那么说明,当前的最长链的两端都在相邻节点所确定的子树中。

所以我们往这颗子树中走就用可能是更优的。(随时取min)

为什么说是可能?因为这个最长链的位置可能改动。


对于这个二次函数图像,我们可以使用一个类似二分的方法,在log时间复杂度中找到最小值。

就是前文说的类似单调性一样的东西。

所以我们可以利用最长连所在的子树的重心进行检验。

因为重心的性质,我们就可以每次将问题至少缩小一半规模。

至于什么时候退出呢?

要么递归到底,要么子树重心的答案大于当前最优答案。

#include 
#include
#include
#include
using std::min;using std::max;const int maxn=101000;const int inf=0x7fffffff;struct node{ int p; int value; int nxt;};node line[maxn<<1];int head[maxn],tail;int query[maxn][2];int vis[maxn],dis[maxn],size[maxn],f[maxn];int belong[maxn];int n,m,root,sum;int ans,where;int read(){ char c=getchar(); int res=0; while(c>'9'||c<'0') c=getchar(); while(c>='0'&&c<='9') { res=(res<<1)+(res<<3)+c-'0'; c=getchar(); } return res;}void add(int a,int b,int c){ line[++tail].p=b; line[tail].value=c; line[tail].nxt=head[a]; head[a]=tail; return ;}void get_dis(int now,int fa,int Dis,int Belong){ dis[now]=Dis; belong[now]=Belong; for(int i=head[now];i;i=line[i].nxt) { int v=line[i].p; if(v==fa) continue; get_dis(v,now,Dis+line[i].value,Belong); } return ;}void get_size(int now,int fa){ size[now]=1; for(int i=head[now];i;i=line[i].nxt) { int v=line[i].p; if(vis[v]||v==fa) continue; get_size(v,now); size[now]+=size[v]; } return ;}void get_hry(int now,int fa){ size[now]=1;f[now]=0; for(int i=head[now];i;i=line[i].nxt) { int v=line[i].p; if(vis[v]||v==fa) continue; get_hry(v,now); size[now]+=size[v]; f[now]=max(f[now],size[v]); } f[now]=max(f[now],sum-size[now]); if(f[now]
Max)// {// ans=Max;// where=root;// } for(int i=1;i<=m;i++) { int A=query[i][0],B=query[i][1]; if(dis[A]+dis[B]!=Max) continue; if(belong[A]==belong[B]&&(!Be||Be==belong[A])) Be=belong[A]; else if((!belong[A]||!belong[B])&&(!Be||Be==belong[A]+belong[B])) Be=belong[A]+belong[B]; else return ; } for(int i=head[root];i;i=line[i].nxt) if(!vis[line[i].p]&&Be==belong[line[i].p]) { solve(line[i].p); return ; } return ;}int main(){ n=read();m=read(); for(int i=1,a,b,c;i

转载于:https://www.cnblogs.com/Lance1ot/p/10293284.html

你可能感兴趣的文章
IOS基础学习
查看>>
PHP 导出 Excell
查看>>
Java基础教程——网络基础知识
查看>>
自己到底要的是什么
查看>>
Kruskal基础最小生成树
查看>>
ubuntu 14.04 安装搜狗拼音输入法
查看>>
浅谈算法和数据结构: 一 栈和队列
查看>>
Java内部类详解
查看>>
【hdu 1429】胜利大逃亡(续)
查看>>
图论-次短路求法
查看>>
What's New for Visual C# 6.0
查看>>
ExtJs学习笔记之ComboBox组件
查看>>
关于收费软件
查看>>
getopt_long
查看>>
TensorFlow MNIST CNN 代码
查看>>
javascript之Style物
查看>>
JSON跨域解决方案收集
查看>>
SSH框架整合总结
查看>>
图的深度优先遍历
查看>>
C# 之 提高WebService性能大数据量网络传输处理
查看>>