LINK:城市

谢邀,学弟说的一道毒瘤题。

没有真正的省选题目毒瘤 或者说 写O(n)的做法确实毒瘤。

这里给一个花20min就写完的非常好写的暴力。

容易想到枚举哪条边删掉 删掉之后考虑在哪两个点上加。

一个比较重要的性质是 联通两个连通块之后 大联通块的直径端点一定有一端属于原来两个联通块的直径端点之一。

也就是合并两个连通块 直径等于=max(左边直径,右边直径,链接起来的直径)

其中前两者固定 考虑让第三者最小 进一步可以分析得到 那两个点的贡献是到自己连通块内的最长距离的点。

分别最小化之后显然是直径上的中点。

一个比较有意思的事实:实际上直径的中点可能在两个节点之间 那么此时这两个节点的贡献相同 所以选哪个都行。

沿着直径找中点过于繁琐 可以直接从直径两端bfs 然后每个点的贡献为max(dis1[x],dis2[x]).

这样就很好写了。值得一提的是 我的写法没有加入过多的优化 每次需要6遍bfs,所以常数有点大。

卡常:容易发现 如果删的不是直径上的边那么对答案没有贡献 可以直接枚举删直径上的边。

考虑求出左边的直径之后进行最优性剪枝 比当前答案大就没必要再做了。

进一步的可以将bfs的次数卡一下 只删直径上的边之后 一个比较重要的性质是 原来树中的直径依然还是分属两个连通块的两端。

这样bfs的次数只有4次了。

进一步的 可以由此推出O(n)的做法 沿着直径删边 然后 每次便利多出来的部分 由上次直径推出当前直径 复杂度就降到O(n)了 不过实现起来过于繁琐 我就没实现。

经过优化的code:n^2 十个测试点跑了400多ms 我也很骄傲~

const int MAXN=5010;
int n,ans,id,flag,len=1,t,h,c1,c2;
int vis[MAXN],c[MAXN<<1],dis[MAXN],q[MAXN],dis1[MAXN],s1,s2,s3,mark;
int lin[MAXN],e[MAXN<<1],ver[MAXN<<1],nex[MAXN<<1];
inline void add(int x,int y,int z)
{
ver[++len]=y;
nex[len]=lin[x];
lin[x]=len;
e[len]=z;
}
inline int bfs(int s)
{
++id;t=h=0;int mx=0,p=s;
q[++t]=s;vis[s]=id;dis[s]=0;
while(++h<=t)
{
int x=q[h];
go(x)
{
if(i==(mark^1)||i==mark)continue;
if(vis[tn]!=id)
{
vis[tn]=id;
dis[tn]=dis[x]+e[i];
q[++t]=tn;
if(dis[tn]>mx)mx=dis[tn],p=tn;
}
}
}
return p;
}
inline void bfs1(int s,int &w)
{
++id;t=h=0;w=INF;
q[++t]=s;vis[s]=id;dis1[s]=0;
while(++h<=t)
{
int x=q[h];
w=min(w,max(dis[x],dis1[x]));
go(x)
{
if(i==(mark^1)||i==mark)continue;
if(vis[tn]!=id)
{
vis[tn]=id;
dis1[tn]=dis1[x]+e[i];
q[++t]=tn;
}
}
}
}
inline void dfs(int x,int fa)
{
if(x==c2){flag=1;return;}
go(x)
if(tn!=fa)
{
dfs(tn,x);
if(flag)
{
c[i]=c[i^1]=1;
return;
}
}
}
int main()
{
freopen("1.in","r",stdin);
get(n);
rep(2,n,i)
{
int get(x),get(y),get(z);
add(x,y,z);add(y,x,z);
}
c1=bfs(1);c2=bfs(c1);
dfs(c1,0);ans=dis[c2];
for(int i=2;i<=len;i+=2)
{
if(!c[i])continue;
mark=i;
int w1=bfs(c1);
if(dis[w1]>=ans)continue;
bfs1(w1,s1);
int w2=bfs(c2);
if(dis[w2]>=ans)continue;
bfs1(w2,s2);
ans=min(ans,max(dis[w1],max(dis[w2],s2+s1+e[i])));
}
put(ans);return 0;
}

luogu P3761 [TJOI2017]城市 树的直径 bfs的更多相关文章

  1. [TJOI2017] 城市 (树的直径,贪心)

    题目链接 Solution 这道题,调了我一晚上... 一直80分 >_<|| ... 考虑到几点: 分开任意一条边 \(u\) ,那么其肯定会断成两棵树. 肯定是分开直径上的边最优,否则 ...

  2. poj2631 树的直径 + bfs

    //Accepted 492 KB 0 ms //树的直径 bfs #include <cstdio> #include <cstring> #include <iost ...

  3. [洛谷P3761] [TJOI2017]城市

    洛谷题目链接:[TJOI2017]城市 题目描述 从加里敦大学城市规划专业毕业的小明来到了一个地区城市规划局工作.这个地区一共有ri座城市,<-1条高速公路,保证了任意两运城市之间都可以通过高速 ...

  4. bzoj4890[Tjoi2017]城市(树的半径)

    4890: [Tjoi2017]城市 Time Limit: 30 Sec  Memory Limit: 128 MBSubmit: 149  Solved: 91[Submit][Status][D ...

  5. hdu2196 树的直径 + bfs

    //Accepted 740 KB 15 ms //树的直径 //距离一个顶点最远的点一定是树的直径的一个端点 #include <cstdio> #include <cstring ...

  6. [LOJ3014][JOI 2019 Final]独特的城市——树的直径+长链剖分

    题目链接: [JOI 2019 Final]独特的城市 对于每个点,它的答案最大就是与它距离最远的点的距离. 而如果与它距离为$x$的点有大于等于两个,那么与它距离小于等于$x$的点都不会被计入答案. ...

  7. LG5536 「XR-3」核心城市 树的直径

    问题描述 LG5536 题解 两次 \(\mathrm{dfs}\) 求树的直径. 然后找到树的直径的中点. 然后按照 子树中最深的点深度-自己深度 排序,贪心选取前 \(k\) 个. \(\math ...

  8. 树上选两点(使最短)树的直径+bfs

    题意: 给你一颗树,让你放两个点,放在哪里的时候任意点到某个最近的消防站最远值最小. 思路: 树的直径类题目. 首先我们想两个点会把整棵树分成两个团,所以肯定会在树的某个链上切开. 而且要切一定切在树 ...

  9. ZOJ 3820 Building Fire Stations 求中点+树的直径+BFS

    题意:给一棵树,要求找出两个点,使得所有点到这两个点中距离与自己较近的一个点的距离的最大值(所有点的结果取最大的值,即最远距离)最小. 意思应该都能明白. 解法:考虑将这棵树摆直如下: 那么我们可以把 ...

随机推荐

  1. Golden Tiger Claw,题解

    题目链接 题目: 题意: 找到和最小的两个序列a,b满足对于任意i,j有a[i]+b[j]>=c[i][j](矩阵c给出). 分析: 首先很容易看出来要使这题要用KM算法,为啥呢?因为要最小化a ...

  2. DLL注入之修改PE静态注入

    DLL注入之修改PE静态注入 0x00 前言 我们要注入的的力量功能是下载baidu首页数据.代码如下: #include "stdio.h" #include"stdi ...

  3. React-redux使用

    为什么要使用react-redux 由于redux的store与组件的耦合度太高所以,我们用react官方提供的react-redux可以使两者耦合度降低,更好的实现模块化开发. react-redu ...

  4. Window - 安装 ant

    官方下载地址 https://ant.apache.org/bindownload.cgi 旧版下载地址 https://archive.apache.org/dist/ant/binaries/ 挑 ...

  5. requests接口自动化1-json序列化与反序列化

    json序列化与反序列化: 序列化:将对象转换为json字符串 反序列化:将json字符串转换为对象,比如转换为python里的字典 import json #定义字典 dict1={'usernam ...

  6. java 基本语法(十四)Lambda (一)表达式

    1.Lambda表达式使用前后的对比:举例一: @Test public void test1(){ Runnable r1 = new Runnable() { @Override public v ...

  7. java IO流 (一) File类的使用

    1.File类的理解* 1. File类的一个对象,代表一个文件或一个文件目录(俗称:文件夹)* 2. File类声明在java.io包下* 3. File类中涉及到关于文件或文件目录的创建.删除.重 ...

  8. ASP.NET Core静态文件处理源码探究

    前言     静态文件(如 HTML.CSS.图像和 JavaScript)等是Web程序的重要组成部分.传统的ASP.NET项目一般都是部署在IIS上,IIS是一个功能非常强大的服务器平台,可以直接 ...

  9. Ethical Hacking - NETWORK PENETRATION TESTING(21)

    MITM - Code Injection Inject javascript or HTML code into pages. Code gets executed on target machin ...

  10. Substance Designer学习资料参考及学习入门感受

    先奉上大佬写的: 名称:Substance Designer 萌新入门流程 地址:https://zhuanlan.zhihu.com/p/56194917 作者:ShadowjackLeeSD小菜鸡 ...