ZOJ 3820 Building Fire Stations

题意:

树上找两个点  使得其它点到这两点随意一点的距离的最大值最小

思路:

最大值最小  想到二分  在二分的基础上判定这个最大值是否可能

怎样判定这个问题就是怎样选那两个点的问题  非常明显  我们要处理的是直径(不然没意义  最长的就是直径)  那么既然已经有了一个要判定的值x  最好还是就选择距离直径两端点距离为x的点就好

直径上的点最多n个  算上二分的复杂度  O(nlogn)能够解决

代码:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<map>
#include<set>
#include<vector>
#include<queue>
#include<cstdlib>
#include<ctime>
#include<cmath>
using namespace std;
typedef long long LL;
#define N 200010 int t, n;
struct edge {
int v, next;
} ed[N * 2];
int head[N], tot;
int dis[N], pre[N];
int route[N], m; void add(int u, int v) {
ed[tot].v = v;
ed[tot].next = head[u];
head[u] = tot++;
} int qu[N];
int bfs(int u) {
int l = 0, r = 1;
int pos = u, val = 0;
dis[u] = 0;
qu[0] = u;
while (l < r) {
u = qu[l++];
for (int i = head[u]; ~i; i = ed[i].next) {
int v = ed[i].v;
if (dis[v] == -1) {
pre[v] = u;
dis[v] = dis[u] + 1;
qu[r++] = v;
if (dis[v] > val) {
val = dis[v];
pos = v;
}
}
}
}
return pos;
} int flag[N];
bool yes(int ans) {
memset(flag, 0, sizeof(flag));
memset(dis, -1, sizeof(dis));
bfs(route[ans]);
for (int i = 1; i <= n; i++) {
if (dis[i] <= ans)
flag[i] = 1;
}
memset(dis, -1, sizeof(dis));
bfs(route[m - 1 - ans]);
for (int i = 1; i <= n; i++) {
if (dis[i] <= ans)
flag[i] = 1;
}
for (int i = 1; i <= n; i++) {
if (!flag[i])
return false;
}
return true;
} int main() {
int i, u, v;
scanf("%d", &t);
while (t--) {
tot = 0;
memset(head, -1, sizeof(head));
scanf("%d", &n);
for (i = 1; i < n; i++) {
scanf("%d%d", &u, &v);
add(u, v);
add(v, u);
}
memset(dis, -1, sizeof(dis));
u = bfs(1);
memset(dis, -1, sizeof(dis));
memset(pre, -1, sizeof(pre));
v = bfs(u);
m = 0;
while (v != -1) {
route[m++] = v;
v = pre[v];
}
int l = 0, r = m - 1, mid, ans[3];
while (l <= r) {
mid = (l + r) / 2;
if (yes(mid)) {
ans[0] = mid;
ans[1] = route[mid];
ans[2] = route[m - 1 - mid];
if (ans[1] == ans[2]) {
for (i = 0; i < m; i++) {
if (route[i] != ans[1]) {
ans[2] = route[i];
break;
}
}
}
r = mid - 1;
} else
l = mid + 1;
}
printf("%d %d %d\n", ans[0], ans[1], ans[2]);
}
return 0;
}
上一篇:HttpWebRequest 请求带OAuth2 授权的webapi


下一篇:Ubuntu下tomcat或eclipse启动提示没有java环境问题