题目描述

mhy12345学习了树的直径,于是开始研究图的半径,具体来说,我们需要在图中选定一个地方作为中心,其中这个中心有可能在路径上。

而这个中心的选址需要能够使得所有节点达到这个中心的最短路里面最大值最小(也就是说离中心最远的结点距离尽可能小),求出这个最大值的最小值,作为图的半径。

数据范围

N<=200,W<=100000,M<=19900

数据有梯度

分析与演绎

原题所求:选取一个实点,使得图上所有结点到这个实点的最长距离最短

由于实点既可以取在边上,也可以取在结点上,所以可取范围很大,难以处理。

花费O(m),原题所求转化为在一条边上选取一个实点,使得图上所有结点到这个实点的最长距离最短

预设花费来枚举这条边上的一个实点,原题继续转化图上所有点到一个实点的最长距离最短是多少

这就让我们感到很舒服,设这条边为(x,y)权为z,实点在与x距离为t,这个答案为ans:

ans=max{min(dis[i][x]+t,dis[i][y]+z−t)}

我们可以利用O(n)的时间来求得答案,但总的复杂度很高。


目前演绎的代价还是很大的,考虑继续分析。

考虑对时间复杂度影响最大的步骤,就是枚举一条边上实点的步骤。

这个复杂度为O(+∞)。

考虑交集优化:

随着t从x到y的动态过程, 显然有很多实点冗余的。

对于这样的动态过程,可以考虑刻画图像来反映变化过程。

由于dis[i][x]+t是增函数,dis[i][y]+z−t是减函数,并且它们都是斜率为1或-1的一次函数。

它们要取最小值,所以它们合起来就是一个锯齿形。如下图。



n个锯齿形图像堆叠到一起。

使它们取较大值,最终图像为:



然后,我们要取这个图像上最低一点。

显然最低点都存在于两峰之间。

一个t值为峰当且仅当满足dis[i][x]+t=dis[i][y]+z−t。

这个一次方程易求解,所以n个峰值及其横坐标我们可以花O(n)代价得知。

既然最低点只存在于两峰之间,那么我们将每个峰值横坐标排序。

取两峰的编号v,v+1,这个转折点即是满足dis[v][y]+t=dis[v+1][x]+z−t的t值。

给所有转折点(即最低点)取最小值即为这条边的答案。


总的时间复杂度为O(mnlogn)。

代码

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#define ll long long
using namespace std;
const char* fin="center.in";
const char* fout="center.out";
const int inf=0x7fffffff;
const int maxn=207,maxm=40007;
int n,m,i,j,k,l;
int f[maxn][maxn],a[maxm][3];
double ans=0,ans1,c1,c2,x;
struct node{
int x,y;
}c[maxn];
bool cmp(node a,node b){
return a.x>b.x || a.x==b.x && a.y<b.y;
}
void floyd(){
int i,j,k;
for (k=1;k<=n;k++)
for (i=1;i<=n;i++)
for (j=1;j<=n;j++){
if (f[i][k]>2000000000 || f[k][j]>2000000000) continue;
f[i][j]=min(f[i][j],f[i][k]+f[k][j]);
}
}
int main(){
freopen(fin,"r",stdin);
freopen(fout,"w",stdout);
scanf("%d%d",&n,&m);
memset(f,127,sizeof(f));
for (i=1;i<=n;i++) f[i][i]=0;
for (i=1;i<=m;i++){
scanf("%d%d%d",&j,&k,&l);
a[i][0]=j;
a[i][1]=k;
a[i][2]=l;
f[j][k]=min(f[j][k],l);
f[k][j]=min(f[k][j],l);
}
floyd();
ans=inf;
for (i=1;i<=m;i++){
ans1=0;
for (j=1;j<=n;j++) c[j].x=f[j][a[i][0]],c[j].y=f[j][a[i][1]];
sort(c+1,c+n+1,cmp);
c1=0;
for (j=1;j<n;j++){
c2=c[j+1].x;
c1=max(c1,(double)c[j].y);
if (c1<c2 && c1+a[i][2]<c2 || c1>c2 && c2+a[i][2]<c1) continue;
ans=min(ans,(c1+a[i][2]+c2)*0.5);
}
}
printf("%.2lf",ans);
return 0;
}

启发

考虑某个值得动态变化过程,可以刻画图像。

【JZOJ4884】【NOIP2016提高A组集训第12场11.10】图的半径的更多相关文章

  1. 【JZOJ4883】【NOIP2016提高A组集训第12场11.10】灵知的太阳信仰

    题目描述 在炽热的核熔炉中,居住着一位少女,名为灵乌路空. 据说,从来没有人敢踏入过那个熔炉,因为人们畏缩于空所持有的力量--核能. 核焰,可融真金. 咳咳. 每次核融的时候,空都会选取一些原子,排成 ...

  2. 【JZOJ4882】【NOIP2016提高A组集训第12场11.10】多段线性函数

    题目描述 数据范围 解法 三分找出极值,两个二分找出极值的范围. 代码 #include<iostream> #include<stdio.h> #include<str ...

  3. JZOJ 【NOIP2016提高A组集训第16场11.15】兔子

    JZOJ [NOIP2016提高A组集训第16场11.15]兔子 题目 Description 在一片草原上有N个兔子窝,每个窝里住着一只兔子,有M条路径连接这些窝.更特殊地是,至多只有一个兔子窝有3 ...

  4. JZOJ 【NOIP2016提高A组集训第16场11.15】SJR的直线

    JZOJ [NOIP2016提高A组集训第16场11.15]SJR的直线 题目 Description Input Output Sample Input 6 0 1 0 -5 3 0 -5 -2 2 ...

  5. 【NOIP2016提高A组集训第14场11.12】随机游走

    题目 YJC最近在学习图的有关知识.今天,他遇到了这么一个概念:随机游走.随机游走指每次从相邻的点中随机选一个走过去,重复这样的过程若干次.YJC很聪明,他很快就学会了怎么跑随机游走.为了检验自己是不 ...

  6. 【NOIP2016提高A组集训第14场11.12】随机游走——期望+树形DP

    好久没有写过题解了--现在感觉以前的题解弱爆了,还有这么多访问量-- 没有考虑别人的感受,没有放描述.代码,题解也写得歪歪扭扭. 并且我要强烈谴责某些写题解的代码不打注释的人,像天书那样,不是写给普通 ...

  7. 【JZOJ4890】【NOIP2016提高A组集训第14场11.12】随机游走

    题目描述 YJC最近在学习图的有关知识.今天,他遇到了这么一个概念:随机游走.随机游走指每次从相邻的点中随机选一个走过去,重复这样的过程若干次.YJC很聪明,他很快就学会了怎么跑随机游走.为了检验自己 ...

  8. 【JZOJ4889】【NOIP2016提高A组集训第14场11.12】最长公共回文子序列

    题目描述 YJC最近在学习字符串的有关知识.今天,他遇到了这么一个概念:最长公共回文子序列.一个序列S,如果S是回文的且分别是两个或多个已知序列的子序列,且是所有符合此条件序列中最长的,则 S 称为已 ...

  9. 【JZOJ4888】【NOIP2016提高A组集训第14场11.12】最近公共祖先

    题目描述 YJC最近在学习树的有关知识.今天,他遇到了这么一个概念:最近公共祖先.对于有根树T的两个结点u.v,最近公共祖先LCA(T,u,v)表示一个结点x,满足x是u.v的祖先且x的深度尽可能大. ...

随机推荐

  1. CentOS 6.5 usb安装

    我只说一下将CentOS安装作为服务器的情况,但是适用于普遍的CentOS安装过程,首先下载CentOS的安装镜像文件,有这么几种:CentOS-6.5-x86_64-LiveCD.CentOS-6. ...

  2. 《DSP using MATLAB》Problem 7.31

    参照Example7.27,因为0.1π=2πf1   f1=0.05,0.9π=2πf2   f2=0.45 所以0.1π≤ω≤0.9π,0.05≤|H|≤0.45 代码: %% +++++++++ ...

  3. python intern(字符串驻留机制)

    python 中为了提高字符串的使用用效率和节约内存,对于由 字母.数字.下划线组成的标识符采用了 intern 机制,即对于短字符串,将其赋值给多个对象时,内存中只有一个副本,多个对象共享这个副本. ...

  4. 【One by one系列】一步步开始使用Redis吧(一)

    One by one,一步步开始使用Redis吧(一) 最近有需求需要使用redis,之前也是随便用用,从来也没有归纳总结,今天想睡觉,但是又睡不着,外面阳光不错,气温回升了,2019年6月1日,成都 ...

  5. Redis使用:聚合类型为空时,会自动被Redis删除

    项目中使用Redis来记录用户的上线和下线信息,其中用到了集合(sets)类型,某用户上线时,向sets中添加数据,下线时将相应数据从sets中删除,考虑当该用户的所有实例都下线时,需要将sets删除 ...

  6. Highcharts 饼图数值显示在图形上

    1.引用js文件 <script type="text/javascript" src="http://cdn.hcharts.cn/jquery/jquery-1 ...

  7. C#多线程之间事件通知

    我有两个线程,线程1接受网络数据,存到队列;线程2取队列,进行各种复杂的处理然后绘制到界面上;想让线程1有数据了通知线程2,线程2再取队列,因为不通知的话,线程2一直在while循环检索队列时候有东西 ...

  8. SpringBoot+Shiro+mybatis整合实战

    SpringBoot+Shiro+mybatis整合 1. 使用Springboot版本2.0.4 与shiro的版本 引入springboot和shiro依赖 <?xml version=&q ...

  9. Pycharm 2018激活(Mac版)

    第一步,修改host文件 目的:是屏蔽掉Pycharm对激活码的验证 路径:/etc/hosts 在文件最后一行添加文本: 0.0.0.0 account.jetbrains.com 修改后文件如下: ...

  10. linux如何将分组权限置为空

    两种方法 方法一:使用-符号 chmod g=- monkey.py#可以单独指定一个 方法二:简写方式,用0表示 chmod 740 monkey.py#必须同时指定三个的权限