道路改建
来源:互联网 发布:网络基础架构设计方案 编辑:程序博客网 时间:2024/05/01 06:56
题目描述 一个由n户人家组成的村庄,用n-1条路径连接,形成一棵树。
现在进行道路改建,先把某条边的删除,再用这条边连接其他两个点(保持长度相同)。
使得最后村庄之间仍能相互到达,且最远的两个村庄之间的距离最小。
输入 第一行一个整数n,表示村庄的个数。
接下来n-1行,每行3个整数a、b、c,表示有一条路径连接编号为a和b的村庄(编号从0开始)。
输出 输出可以使最远距离达的最小值。
对于100%的数据,n的范围[1,5000],0≤a,b≤n-1,1≤c≤10000;
一道很不错的树的题目
主要的思考点在于
如何找到树上任意一结点的最远值和如何更新答案
根据题目描述
在切断一条边后
一棵树(A)会被分成两棵树(B,C)
这时答案会有三种情况:
1.B的直径
2.C的直径
3.两棵树重新连接后形成的新的直径
我们要做的就是使3最小
设新边连接两点为a,b
这个直径的组成为len1+len2+len3
len1为a在A树上的最远距离
len2为b在B树上的最远距离
len3为被删除边的长度
先在要解决的就是如何快速地求出每个点的最远距离
这里可以使用三遍dfs
第一次找到最远点x1
第二次找到直径的另一个端点x2(同时求出每个点到x1的距离)
第三次从x2出发,求出x2到任意点的距离
ps:节点的距离最大值一定是直径两个端点的任意一点
为了使代码较为简洁可以用结构体包起来
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<vector>using namespace std;#define FOR(i,x,y) for(int i=(x);i<(y);i++)//左闭右开 #define DOR(i,x,y) for(int i=(x);i>(y);i--)#define M 5005#define oo 1000000000int n;inline void chk_mi(int &x,int y){if(x>y)x=y;}inline void chk_mx(int &x,int y){if(x<y)x=y;}//三遍dfs找到每个点的对应最远点struct node{int id,v;};vector<node>edge[M];struct Tree{ int mxdis,cdis;//树的直径 和 到最远点最近的距离 int pa,pb;//断开的两点 int dx;//树直径的一个端点 int fa[M][2];//第一维装父亲 第二位装大小 int dis[M]; void dfs(int x,int f,int d){ chk_mx(dis[x],d); if(d>mxdis){mxdis=d;dx=x;} FOR(i,0,edge[x].size()){ int y=edge[x][i].id; if(y==f)continue; if((x==pa&&y==pb)||(x==pb&&y==pa))continue; dfs(y,x,d+edge[x][i].v); fa[y][0]=x;fa[y][1]=edge[x][i].v; } } void solve(int a,int b){//注意初始化!!! memset(fa,0,sizeof(fa)); memset(dis,-1,sizeof(dis)); pa=a;pb=b; mxdis=0; dfs(a,-1,0);//找最大点 mxdis=0;dfs(dx,-1,0);//以dx为根建树 同时跟新dx-->变成另外一个端点 mxdis=0;fa[dx][0]=-1;dfs(dx,-1,0); cdis=oo; FOR(i,0,n){ if(dis[i]==-1)continue; chk_mi(cdis,dis[i]); } }}A,B,C; int main(){ cin>>n; FOR(i,1,n){ int a,b,c; scanf("%d %d %d",&a,&b,&c); edge[a].push_back((node){b,c}); edge[b].push_back((node){a,c}); } A.solve(0,-1); int x=A.dx,ans=A.mxdis; while(A.fa[x][0]!=-1){ int y=A.fa[x][0]; B.solve(x,y); C.solve(y,x); chk_mi(ans,max(max(B.mxdis,C.mxdis),B.cdis+C.cdis+A.fa[x][1])); x=y; } printf("%d\n",ans); return 0;}
阅读全文
2 0
- 道路改建
- Jzoj3486 道路改建
- [jzoj]3486. 【NOIP2013模拟联考10】道路改建(rebuild)(缩环+Tarjan+拓扑+bitset记录状态)
- 3486. 【NOIP2013模拟联考10】道路改建(rebuild)(2017.12A组)(tarjan缩环+拓补排序+DP+bitset)
- 网站的从新改建
- 道路
- 道路
- 道路
- 探讨魔兽dota改建原理
- jQ改建回车改为Tab
- 新建、扩建、改建、技改区分
- WIN32编写Warkey 实现改建
- MZOJ2007:路灯的改建计划
- 2651: 城市改建 树形DP
- MFC做的魔兽改建精灵
- window 自带小工具的改建
- 魔兽改建程序源码(一)
- 硬件道路: 软件道路:
- Caffe_Windows学习笔记(二)用自己的数据训练和测试CaffeNet
- Android 开发之录音与播放
- Spring JDBC-混合框架的事务管理
- 数据库锁总结
- [LeetCode]21. Merge Two Sorted Lists
- 道路改建
- Java 打包 jar 运行
- Eclipse导入Java项目时“No projects are found to import”错误的处理,
- frameworks/av/media/CedarX-Projects/CedarAndroidLib/LIB_KK44_/Android.mk: No such file or directory
- 地上有一个m行和n列的方格。一个机器人从坐标0,0的格子开始移动,每一次只能向左,右,上,下四个方向移动一格,但是不能进入行坐标和列坐标的数位之和大于k的格子。
- C++基础-this指针/内联函数
- iOS-月日期,本月初始第一天和最后一天,以及比较两个日期的类方法
- 当Listview中的item与其中的Button/CheckBox的点击事件冲突时……
- 机器学习零基础?手把手教你用TensorFlow搭建图像识别系统