zoj3820
题意:给定一个树,找出两个点,使得其他点到最近的点的距离最小
思路:
牡丹江站的B题。。可惜当时坑的不大对,最后也没写完。。
1、题解方法:
基于一个结论,答案一定在直径上(证明我不会)。。
那么,可以先求出直径,然后直接二分,二分完后o(n)判定,时间复杂度为nlogn
2、我的方法:
赛场上写的,可惜最后由于各种原因没写完,代码难度实在比题解高多了,可惜想到了就不敢在猜想其他方法了了。。
可以很容易证明,题目等价于对于删除某条边后求剩余两棵树直径,然后取一个最小的。。
那么,就可以用树形dp的方法,维护每个点为子树的前三长链(以根为起始,并且来源于不同子树),还有不经过根的前两大答案,以及以其为根的子树的答案。
先一边求完后,然后从根递推到以每个点为根成为一个树,其余为另外一棵树的答案啊。。
这样时间复杂度为o(n)
code(nlog(n)):
#include <bits/stdc++.h>
#define M0(a, b) memset(a, 0, sizeof(int) * (b+10))
using namespace std;
const int maxn = ;
int z[maxn], inz[maxn], pos[maxn], from[maxn];
int L[maxn], R[maxn], cov[maxn];
vector<int> e[];
int n, m;
int ans, ansx, ansy; void init(){
scanf("%d", &n);
for (int i = ; i <= n; ++i)
e[i].clear();
int u, v;
for (int i = ; i < n; ++i){
scanf("%d%d", &u, &v);
e[u].push_back(v);
e[v].push_back(u);
}
} int pre[maxn], inq[maxn], dis[maxn];
void bfs(int s, int &rt){
queue<int> q;
M0(inq, n), M0(dis, n), M0(pre, n);
q.push(s), dis[s] = , inq[s] = ;
int u, v;
while (!q.empty()){
u = q.front();
q.pop();
for (int i = ; i < (int)e[u].size(); ++i){
v = e[u][i];
if (!inq[v])
dis[v] = dis[u] + , inq[v] = , q.push(v), pre[v] = u;
}
}
rt = s;
for (int i = ; i <= n; ++i)
if (dis[rt] < dis[i]) rt = i;
} void bfs(){
queue<int> q;
M0(inq, n), M0(dis, n), M0(from, n);
for (int i = ; i <= m; ++i)
q.push(z[i]), inq[z[i]] = , from[z[i]] = i, dis[z[i]] = ;
int u, v;
while (!q.empty()){
u = q.front();
q.pop();
for (int i = ; i < (int)e[u].size(); ++i){
v = e[u][i];
if (!inq[v])
dis[v] = dis[u] + , inq[v] = , q.push(v), from[v] = from[u];
}
}
} int check(const int len, int& x, int &y){
M0(L, n), M0(R, n), M0(cov, n);
int d;
int mleft = m + , mright = ;
for (int i = ; i <= n; ++i){
d = len - dis[i];
if (d < ) return ;
L[i] = max(, from[i] - d);
R[i] = min(m, from[i] + d);
mleft = min(mleft, R[i]);
mright = max(mright, L[i]);
}
for (int i = ; i <= n; ++i)
if ((L[i] <= mleft && R[i] >= mleft) || (L[i] <= mright && R[i] >= mright)) continue;
else return ;
x = mleft, y = mright;
if (x == y)
(y < m) ? ++y : --x;
return ;
} void solve(){
int s, t;
bfs(, s), bfs(s, t);
m = ;
M0(inz, n), M0(pos, n);
while (t) z[++m] = t, pos[t] = m, t = pre[t];
bfs();
int l = , r = n, mid;
int x, y;
while (l <= r){
mid = (l + r) >> ;
if (check(mid, x, y))
r = mid - , ans = mid, ansx = z[x], ansy = z[y];
else l = mid + ;
}
printf("%d %d %d\n", ans, ansx, ansy);
} int main(){
int cas;
scanf("%d", &cas);
while (cas--){
init();
solve();
}
}
code(o(n)):
#include <bits/stdc++.h>
#define x first
#define y second
#define M0(a) memset(a, 0, sizeof(int) * (n+10))
#define Inf 0x3fffffff
using namespace std;
const int maxn = ;
vector<int> e[maxn];
pair<int, int> len[maxn][], ans2[maxn][], tmp[], one(, ), zero(, );
int fa[maxn], ans1[maxn], n, ans[maxn], z[maxn];
int ans_x, ans_y, ans_len; int inq[maxn], dis[maxn], pre[maxn];
int pos[maxn], tot;
void bfs(){
M0(inq), M0(fa);
queue<int> q;
q.push(), inq[] = , pos[tot = ] = ;
int u, v;
while (!q.empty()){
u = q.front();
q.pop();
for (int i = ; i < (int)e[u].size(); ++i){
v = e[u][i];
if (!inq[v])
fa[v] = u, q.push(v), inq[v] = , pos[++tot] = v;
}
}
} void gao1(const int& u){
int v;
for (int i = ; i < (int)e[u].size(); ++i){
v = e[u][i];
if (v == fa[u]) continue;
for (int j = ; j < ; ++j) tmp[j] = len[u][j];
tmp[] = make_pair(len[v][].x + , v);
sort(tmp, tmp + , greater<pair<int, int> >());
for (int j = ; j < ; ++j) len[u][j] = tmp[j];
if (ans1[v] > ans2[u][].x){
swap(ans2[u][], ans2[u][]);
ans2[u][] = make_pair(ans1[v], v);
} else if (ans1[v] > ans2[u][].x)
ans2[u][] = make_pair(ans1[v], v);
ans1[u] = max(ans1[u], ans1[v]);
}
ans1[u] = max(ans1[u], len[u][].x + len[u][].x - );
} int ff, s[];
int ss[maxn], max_d[maxn];
void gao2(const int &u){
ff = fa[u];
ss[u] = ss[ff];
if (len[ff][].y == u)
s[] = len[ff][].x, s[] = len[ff][].x;
else if (len[ff][].y == u)
s[] = len[ff][].x, s[] = len[ff][].x;
else
s[] = len[ff][].x, s[] = len[ff][].x;
s[] = max_d[ff];
sort(s, s + , greater<int>() );
ss[u] = max(s[] + s[] - , ss[u]);
max_d[u] = s[] + ;
if (ans2[ff][].y == u)
ss[u] = max(ss[u], ans2[ff][].x);
else
ss[u] = max(ss[u], ans2[ff][].x);
ans[u] = max(ss[u], ans1[u]);
} void pre_do(){
M0(ss), M0(max_d);
for (int i = ; i <= n; ++i){
len[i][] = len[i][] = len[i][] = one;
ans2[i][] = ans2[i][] = zero;
}
} void init(){
scanf("%d", &n);
pre_do();
for (int i = ; i <= n; ++i)
e[i].clear();
int u, v;
for (int i = ; i < n; ++i){
scanf("%d%d", &u, &v);
e[u].push_back(v);
e[v].push_back(u);
}
} void bfs(int s, int &t, const int& other){
queue<int> q;
M0(inq), M0(pre);
memset(dis, -, sizeof(int) * (n+));
q.push(s), dis[s] = , inq[s] = ;
int u, v;
while (!q.empty()){
u = q.front();
q.pop();
for (int i = ; i < (int)e[u].size(); ++i){
v = e[u][i];
if (v == other) continue;
if (!inq[v])
dis[v] = dis[u] + , inq[v] = , q.push(v), pre[v] = u;
}
}
t = s;
for (int i = ; i <= n; ++i)
if (dis[t] < dis[i]) t = i;
} void solve(){
M0(fa), M0(ans1);
bfs();
for (int i = n; i >= ; --i)
gao1(pos[i]);
for (int i = ; i <= n; ++i)
gao2(pos[i]);
int rt = ;
for (int i = ; i <= n; ++i)
if (ans[rt] > ans[i]) rt = i;
// cout << rt << endl;
ans_len = ans[rt] / ;
int x, y;
bfs(rt, x, fa[rt]);
bfs(x, y, fa[rt]);
int m = ;
while (y) z[m++] = y, y = pre[y];
ans_x = z[m/];
bfs(fa[rt], x, rt);
bfs(x, y, rt);
m = ;
while (y) z[m++] = y, y = pre[y];
ans_y = z[m/];
printf("%d %d %d\n",ans_len, ans_x, ans_y); } int main(){
int cas;
scanf("%d", &cas);
while (cas--){
init();
solve();
}
}
zoj3820的更多相关文章
- ZOJ-3820 Building Fire Stations 题解
题目大意: 一棵树,在其中找两个点,使得其他点到这两个的距离的较小值的最大值的最小值及其方案. 思路: 首先显然一棵树的直径的中点到其他点的距离的最大值必定比其他点的小. 那么感性思考一下就将一棵树的 ...
- zoj3820 Building Fire Stations 树的中心
题意:n个点的树,给出n-1条边,每条边长都是1,两个点建立防火站,使得其他点到防火站的最远距离最短. 思路:比赛的时候和队友一开始想是把这两个点拎起来,使得层数最少,有点像是树的中心,于是就猜测是将 ...
- 求树的直径和中心(ZOJ3820)
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5374 Building Fire Stations Time Limit: 5 ...
- zoj3820 树的直径+二分
这题是个遗憾 !!!!!当时一直不敢相信两个站一定在直径上,赛后想想自己真的是脑袋抽风, 如果其中一个站不在直径上就反向的说明了这条不是直径.可以很明白我们可以肯定的是有一个点一定在直径上假如另外一个 ...
随机推荐
- ssm介绍
1.Spring Spring是一个开源框架,Spring是于2003 年兴起的一个轻量级的Java 开发框架,由Rod Johnson 在其著作Expert One-On-One J2EE ...
- MySql5.5 SQL优化 慢查询日志存储
一.MySql的慢查询日志的开启和存储 1.查看是否把没有使用索引的SQL记录到慢查询日志中,查看 log_queries_not_using_indexes 变量; show VARIABLES L ...
- Python.URLs
1. The Future of Asynchronous IO in Python https://medium.com/@paulcolomiets/the-future-of-asynchron ...
- JavaScript.how-to-debug-javascript
How to debug JavaScript code 1. 写一个HTML文件.例如: <!DOCTYPE html> <html> <title>Web Pa ...
- APNS推送服务证书制作 图文详解教程(新)
iOS消息推送的工作机制可以简单的用下图来概括: Provider是指某个iPhone软件的Push服务器,APNS是Apple Push Notification Service的缩写,是苹果的服务 ...
- django admin管理后台中文添加问题
django版本号 1.7.8 #create database mydb character set utf8;#django-admin.py startproject mysite#设置sett ...
- DNA计算机及DNA存储
傅里叶变换到量子水平,可编程元素到原子分子核能,都可以极大的改变有机体(高级有机体都是有寿命的,例如人类),如果可以出现机械体,核能提供能量:并结合类似高级生物大脑的有机体大脑,不断学习进化,甚至优化 ...
- spring学习 六 spring与mybatis整合
在mybatis学习中有两种配置文件 :全局配置文件,映射配置文件.mybatis和spring整合,其实就是把mybatis中的全局配置文件的配置内容都变成一个spring容器的一个bean,让sp ...
- Ubuntu显示实时网速CPU内存等参数
添加库 sudo add-apt-repository ppa:fossfreedom/indicator-sysmonitor 更新软件列表 sudo apt-get update 安装indica ...
- Rest架构风格
一.REST介绍:: 1.REST是英文 Representational State Transfer的缩写 -- 表象化状态转变 或者 表述性状态转移 1.1 REST是 Web服务的一种架构风格 ...