【BZOJ】2237: [NCPC2009]Flight Planning
2015-11-22 13:42
337 查看
题意
\(n(1 \le n \le 2500)\)个点的树,求删掉一条边再加上一条边使得还是一棵树,且任意两点最大距离最小。分析
考虑枚举删掉每一条边,我们只需要考虑如何加边容易求得新树的最大距离。当然是直径的一半咯。
题解
枚举每一条边,然后求两个连通块的直径,然后最大距离\(=max(len1, len2, (len1+1)/2+(len2+1)/2+1)\)#include <bits/stdc++.h> using namespace std; const int N=2505; struct E { int next, to; }e[N<<1]; int ihead , d , cnt, clr, n; void add(int x, int y) { e[++cnt]=(E){ihead[x], y}; ihead[x]=cnt; e[++cnt]=(E){ihead[y], x}; ihead[y]=cnt; } void dfs(int x, int f) { for(int i=ihead[x]; i; i=e[i].next) { int y=e[i].to; if(y==f || i==clr || i==clr-1) { continue; } d[y]=d[x]+1; dfs(y, x); } } int getlen(int x) { memset(d, 0, sizeof(int)*(n+1)); dfs(x, 0); for(int i=1; i<=n; ++i) { if(d[i]>d[x]) { x=i; } } memset(d, 0, sizeof(int)*(n+1)); dfs(x, 0); for(int i=1; i<=n; ++i) { if(d[i]>d[x]) { x=i; } } return d[x]; } int x , y ; int main() { scanf("%d", &n); for(int i=1; i<n; ++i) { scanf("%d%d", &x[i], &y[i]); add(x[i], y[i]); } int ans=n; for(int i=1; i<n; ++i) { clr=i*2; int len1=getlen(x[i]), len2=getlen(y[i]), a=(len1+1)/2, c=(len2+1)/2; ans=min(ans, max(a+c+1, max(len1, len2))); } printf("%d\n", ans); return 0; }
相关文章推荐
- Bulls and Cows
- Leetcode Range Sum Query 2D - Immutable
- 双调旅行售货员问题
- 【C++】中序线索化二叉树及其遍历
- SVM多类分类方法
- 【BZOJ】2216: [Poi2011]Lightning Conductor
- C#使用ODAC向Oracle数据库插入海量实时数据
- iOS引入JavaScriptCore引擎框架(二)
- linux常用命令
- 注册asp.net 4.0 到iis
- 20135205信息安全系统设计基础第十一周学习总结
- 【BZOJ】2212: [Poi2011]Tree Rotations
- iOS 音频学习(二)
- JDBC--处理Blob
- 大数据时代——从谢顿计划说开去
- Android学习手记(6) TabActivity和TabHost
- swoole编译安装
- 【BZOJ】2172: Mario填格子
- coderforce 492B Vanya and Lanterns
- 在Ubuntu 14.04中安装最新版Eclipse