【Luogu】P3761城市(dfs)
emmm我思维好水……
想了一会lct发现好像不对,然后开始转DP稍微有一点思路,然后看了题解……
首先可以枚举边,然后原树被你拆成了两个子树。
设D1D2是两个子树的直径,W1W2是子树内某个点到其他点最长距离的最小值,val是断掉的边的权值
然后呢我们发现此时的答案成为了max(max(D1,D2),W1+W2+val)
然后可以发现W1W2可以通过枚举子树直径上的点求得。
然后这样就TLE了23333
一个大优化是我们可以发现枚举断掉哪条边这个步骤可以变成枚举断掉直径上哪条边,只有这样才能对答案产生影响
然后就快了九倍……
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cctype>
#define maxn 6000
using namespace std;
inline long long read(){
long long num=,f=;
char ch=getchar();
while(!isdigit(ch)){
if(ch=='-') f=-;
ch=getchar();
}
while(isdigit(ch)){
num=num*+ch-'';
ch=getchar();
}
return num*f;
} int n; struct Edge{
int next,to,val;
}edge[maxn*];
int head[maxn],num;
inline void add(int from,int to,int val){
edge[++num]=(Edge){head[from],to,val};
head[from]=num;
} int dis[maxn];
bool vis[maxn]; void find(int x,int fa,int lim){
for(int i=head[x];i;i=edge[i].next){
int to=edge[i].to;
if(to==fa||to==lim) continue;
dis[to]=dis[x]+edge[i].val;
find(to,x,lim);
}
return;
} void record(int x,int fa,int goal){
if(x==goal){
vis[x]=;
return;
}
for(int i=head[x];i;i=edge[i].next){
int to=edge[i].to;
if(to==fa) continue;
record(to,x,goal);
if(vis[to]) vis[x]=;
}
return;
} struct ANSWER{
int x,y;
}; ANSWER ask(int x,int fa){
memset(vis,,sizeof(vis));
memset(dis,-,sizeof(dis));
dis[x]=;
find(x,fa,fa);
int now=;
for(int i=;i<=n;++i)
if(dis[i]>dis[now]) now=i;
dis[now]=;
find(now,now,fa);
int to=;
for(int i=;i<=n;++i)
if(dis[i]>dis[to]) to=i;
record(now,now,to);
ANSWER ans=(ANSWER){dis[to],0x7fffffff};
for(int i=;i<=n;++i)
if(vis[i]) ans.y=min(ans.y,max(dis[to]-dis[i],dis[i]));
return ans;
} bool vie[maxn*]; int main(){
n=read();
for(int i=;i<n;++i){
int from=read(),to=read(),val=read();
add(from,to,val);
add(to,from,val);
}
ask(,);
for(int i=;i<=num;i+=){
if(vis[edge[i].to]==||vis[edge[i+].to]==) continue;
vie[i]=;
}
int ans=0x7fffffff;
for(int i=;i<=num;i+=){
if(vie[i]==) continue;
int from=edge[i].to,to=edge[i+].to,val=edge[i].val;
ANSWER l1=ask(from,to); ANSWER l2=ask(to,from);
// printf("%d %d %d %d %d %d %d\n",from,to,val,l1.x,l1.y,l2.x,l2.y);
ans=min(ans,max(max(l1.x,l2.x),l1.y+l2.y+val));
}
printf("%d\n",ans);
return ;
}
【Luogu】P3761城市(dfs)的更多相关文章
- luogu P1401 城市
题目链接 luogu P1401 城市 题解 二分最小边权,dinic检验 代码 // luogu-judger-enable-o2 /* 二分最小边权,dinic检验 */ #include< ...
- luogu P3761 [TJOI2017]城市 树的直径 bfs
LINK:城市 谢邀,学弟说的一道毒瘤题. 没有真正的省选题目毒瘤 或者说 写O(n)的做法确实毒瘤. 这里给一个花20min就写完的非常好写的暴力. 容易想到枚举哪条边删掉 删掉之后考虑在哪两个点上 ...
- luogu P4842 城市旅行
嘟嘟嘟 好题,好题 刚开始突发奇想写了一个\(O(n ^ 2)\)暴力,结果竟然过了?!后来才知道是上传题的人把单个数据点开成了10s-- 不过不得不说我这暴力写的挺好看的.删边模仿链表删边,加边的时 ...
- [luogu]P1041 传染病控制[dfs]
[luogu]P1041 传染病控制 ——!x^n+y^n=z^n 题目背景 近来,一种新的传染病肆虐全球.蓬莱国也发现了零星感染者,为防止该病在蓬莱国大范围流行,该国政府决定不惜一切代价控制传染病的 ...
- Luogu P1401 城市(二分+网络流)
P1401 城市 题意 题目描述 N(2<=n<=200)个城市,M(1<=m<=40000)条无向边,你要找T(1<=T<=200)条从城市1到城市N的路,使得最 ...
- luogu P1453 城市环路
题目描述 整个城市可以看做一个N个点,N条边的单圈图(保证图连通),唯一的环便是绕城的环路.保证环上任意两点有且只有2条路径互通.图中的其它部分皆隶属城市郊区. 现在,有一位名叫Jim的同学想在B市开 ...
- LUOGU P1453 城市环路(基环树+dp)
传送门 解题思路 一道基环树上$dp$的题,这种题比较套路吧,首先第一遍$dfs$把环找出来,然后对于环上的每一个点都向它子树内做一次树形$dp$,$f[i][0/1]$表示到了$i$这个点选或不选的 ...
- luogu P1784 数独 dfs 舞蹈链 DXL
LINK:数独 这道题好难 比DXL模板题要难上不少. 首先 还是考虑将行当做决策 那么 一共有\(9*9*9=729\) 个决策. 考虑列用来填充 需要有的条件为 某个位置能能放一次\(9*9\) ...
- [TJOI2017]城市 【树的直径+暴力+优化】
Online Judge:Luogu P3761 Label:树的直径,暴力 题目描述 从加里敦大学城市规划专业毕业的小明来到了一个地区城市规划局工作.这个地区一共有n座城市,n-1条高速公路,保证了 ...
随机推荐
- 使用JDK自带的VisualVM进行Java程序的性能分析
VisualVM是什么? VisualVM是JDK自带的一个用于Java程序性能分析的工具,JDK安装完毕后就有啦,在JDK安装目录的bin文件夹下能找到名称为jvisualvm.exe. 要使用Vi ...
- 2012-2013 ACM-ICPC, NEERC, Central Subregional Contest H Milestones1 (暴力)
预处理+暴力,每个颜色都是独立的,求个前缀和,减一减判断一个在区间内颜色是否存在. 算了算复杂度好像有点勉强,但是还是过了,学了主席树以后用主席树在做一下 #include<bits/stdc+ ...
- UVA 1442 Cave 洞穴 (贪心+扫描)
题意:有一个洞穴,每个位置有一个底的高度p[i],和对应顶的高度s[i],要往里面尽量放燃料,要求燃料不能碰到顶,可以无限接近. 题解:制约燃料储放的就是顶的高度了,分别求出设当前储放位置的向两边的延 ...
- Collatz Conjecture
4981: Collatz Conjecture 时间限制: 6 Sec 内存限制: 128 MB提交: 213 解决: 23[提交][状态][讨论版][命题人:admin] 题目描述 In 19 ...
- 2018.4.21 如何正确快速安装/卸载云服务器Centos7安装GUI图形化界面GNOME桌面环境
为云服务哦Centos安装图形化界面GNOME .KDE 1.开始前先验证一下能不能上网 ping www.baidu.com 2.接下来开始安装X(X Window System),命令为 yum ...
- WINDOWS-API:关于线程CreateThread,_beginthead(_beginthreadex),AfxBeginThread
[转]windows多线程编程CreateThread,_beginthead(_beginthreadex)和AfxBeginThread的区别 在Windows的多线程编程中,创建线程的函数主要有 ...
- python之道08
1.有如下文件,a1.txt,里面的内容为: 某某是最好的学校, 全心全意为学生服务, 只为学生未来,不为牟利. 我说的都是真的.哈哈 分别完成以下的功能: a,将原文件全部读出来并打印. 答案 f ...
- 虚拟机设置NAT
需要开启虚拟机网络相关服务, 安装虚拟网卡, 还有必须安装 VMware Tools VMware虚拟机下实现NAT方式上网1. 把你的虚拟网卡VMnet8设置为自动获得IP.自动获得DNS服务器,启 ...
- Bootstrap 标签
本章将讲解bootstrap标签,标签可用于计数,提示和页面上其它的标记显示.使用class.laber来显示标签,如下面的实例所示 <!DOCTYPE html><html> ...
- linux系统下的用户文件句柄数限制
linux系统下的用户文件句柄数限制 文章来源:企鹅号 为什么要修改用户打开的文件数 系统默认单个进程可以打开1024个文件,对于一些应用如tomcat.oracle等,运行时经常open成千上万个文 ...