首页 > 代码库 > ZOJ 3820 Building Fire Stations
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; }
ZOJ 3820 Building Fire Stations
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。