题意:给定一个树,找出两个点,使得其他点到最近的点的距离最小
思路:
牡丹江站的B题。。可惜当时坑的不大对,最后也没写完。。
1、题解方法:
基于一个结论,答案一定在直径上(证明我不会)。。
那么,可以先求出直径,然后直接二分,二分完后o(n)判定,时间复杂度为nlogn
2、我的方法:
赛场上写的,可惜最后由于各种原因没写完,代码难度实在比题解高多了,可惜想到了就不敢在猜想其他方法了了。。
可以很容易证明,题目等价于对于删除某条边后求剩余两棵树直径,然后取一个最小的。。
那么,就可以用树形dp的方法,维护每个点为子树的前三长链(以根为起始,并且来源于不同子树),还有不经过根的前两大答案,以及以其为根的子树的答案。
先一边求完后,然后从根递推到以每个点为根成为一个树,其余为另外一棵树的答案啊。。
这样时间复杂度为o(n)
code(nlog(n)):

1 #include <bits/stdc++.h> 2 #define M0(a, b) memset(a, 0, sizeof(int) * (b+10)) 3 using namespace std; 4 const int maxn = 210000; 5 int z[maxn], inz[maxn], pos[maxn], from[maxn]; 6 int L[maxn], R[maxn], cov[maxn]; 7 vector<int> e[210000]; 8 int n, m; 9 int ans, ansx, ansy; 10 11 void init(){ 12 scanf("%d", &n); 13 for (int i = 0; i <= n; ++i) 14 e[i].clear(); 15 int u, v; 16 for (int i = 1; i < n; ++i){ 17 scanf("%d%d", &u, &v); 18 e[u].push_back(v); 19 e[v].push_back(u); 20 } 21 } 22 23 int pre[maxn], inq[maxn], dis[maxn]; 24 void bfs(int s, int &rt){ 25 queue<int> q; 26 M0(inq, n), M0(dis, n), M0(pre, n); 27 q.push(s), dis[s] = 0, inq[s] = 1; 28 int u, v; 29 while (!q.empty()){ 30 u = q.front(); 31 q.pop(); 32 for (int i = 0; i < (int)e[u].size(); ++i){ 33 v = e[u][i]; 34 if (!inq[v]) 35 dis[v] = dis[u] + 1, inq[v] = 1, q.push(v), pre[v] = u; 36 } 37 } 38 rt = s; 39 for (int i = 1; i <= n; ++i) 40 if (dis[rt] < dis[i]) rt = i; 41 } 42 43 void bfs(){ 44 queue<int> q; 45 M0(inq, n), M0(dis, n), M0(from, n); 46 for (int i = 1; i <= m; ++i) 47 q.push(z[i]), inq[z[i]] = 1, from[z[i]] = i, dis[z[i]] = 0; 48 int u, v; 49 while (!q.empty()){ 50 u = q.front(); 51 q.pop(); 52 for (int i = 0; i < (int)e[u].size(); ++i){ 53 v = e[u][i]; 54 if (!inq[v]) 55 dis[v] = dis[u] + 1, inq[v] = 1, q.push(v), from[v] = from[u]; 56 } 57 } 58 } 59 60 61 int check(const int len, int& x, int &y){ 62 M0(L, n), M0(R, n), M0(cov, n); 63 int d; 64 int mleft = m + 1, mright = 0; 65 for (int i = 1; i <= n; ++i){ 66 d = len - dis[i]; 67 if (d < 0) return 0; 68 L[i] = max(1, from[i] - d); 69 R[i] = min(m, from[i] + d); 70 mleft = min(mleft, R[i]); 71 mright = max(mright, L[i]); 72 } 73 for (int i = 1; i <= n; ++i) 74 if ((L[i] <= mleft && R[i] >= mleft) || (L[i] <= mright && R[i] >= mright)) continue; 75 else return 0; 76 x = mleft, y = mright; 77 if (x == y) 78 (y < m) ? ++y : --x; 79 return 1; 80 } 81 82 void solve(){ 83 int s, t; 84 bfs(1, s), bfs(s, t); 85 m = 0; 86 M0(inz, n), M0(pos, n); 87 while (t) z[++m] = t, pos[t] = m, t = pre[t]; 88 bfs(); 89 int l = 0, r = n, mid; 90 int x, y; 91 while (l <= r){ 92 mid = (l + r) >> 1; 93 if (check(mid, x, y)) 94 r = mid - 1, ans = mid, ansx = z[x], ansy = z[y]; 95 else l = mid + 1; 96 } 97 printf("%d %d %d ", ans, ansx, ansy); 98 } 99 100 int main(){ 101 int cas; 102 scanf("%d", &cas); 103 while (cas--){ 104 init(); 105 solve(); 106 } 107 }
code(o(n)):

1 #include <bits/stdc++.h> 2 #define x first 3 #define y second 4 #define M0(a) memset(a, 0, sizeof(int) * (n+10)) 5 #define Inf 0x3fffffff 6 using namespace std; 7 const int maxn = 210000; 8 vector<int> e[maxn]; 9 pair<int, int> len[maxn][3], ans2[maxn][2], tmp[10], one(1, 0), zero(0, 0); 10 int fa[maxn], ans1[maxn], n, ans[maxn], z[maxn]; 11 int ans_x, ans_y, ans_len; 12 13 int inq[maxn], dis[maxn], pre[maxn]; 14 int pos[maxn], tot; 15 void bfs(){ 16 M0(inq), M0(fa); 17 queue<int> q; 18 q.push(1), inq[1] = 1, pos[tot = 1] = 1; 19 int u, v; 20 while (!q.empty()){ 21 u = q.front(); 22 q.pop(); 23 for (int i = 0; i < (int)e[u].size(); ++i){ 24 v = e[u][i]; 25 if (!inq[v]) 26 fa[v] = u, q.push(v), inq[v] = 1, pos[++tot] = v; 27 } 28 } 29 } 30 31 void gao1(const int& u){ 32 int v; 33 for (int i = 0; i < (int)e[u].size(); ++i){ 34 v = e[u][i]; 35 if (v == fa[u]) continue; 36 for (int j = 0; j < 3; ++j) tmp[j] = len[u][j]; 37 tmp[3] = make_pair(len[v][0].x + 1, v); 38 sort(tmp, tmp + 4, greater<pair<int, int> >()); 39 for (int j = 0; j < 3; ++j) len[u][j] = tmp[j]; 40 if (ans1[v] > ans2[u][0].x){ 41 swap(ans2[u][1], ans2[u][0]); 42 ans2[u][0] = make_pair(ans1[v], v); 43 } else if (ans1[v] > ans2[u][1].x) 44 ans2[u][1] = make_pair(ans1[v], v); 45 ans1[u] = max(ans1[u], ans1[v]); 46 } 47 ans1[u] = max(ans1[u], len[u][0].x + len[u][1].x - 1); 48 } 49 50 int ff, s[5]; 51 int ss[maxn], max_d[maxn]; 52 void gao2(const int &u){ 53 ff = fa[u]; 54 ss[u] = ss[ff]; 55 if (len[ff][0].y == u) 56 s[0] = len[ff][1].x, s[1] = len[ff][2].x; 57 else if (len[ff][1].y == u) 58 s[0] = len[ff][0].x, s[1] = len[ff][2].x; 59 else 60 s[0] = len[ff][0].x, s[1] = len[ff][1].x; 61 s[2] = max_d[ff]; 62 sort(s, s + 3, greater<int>() ); 63 ss[u] = max(s[0] + s[1] - 1, ss[u]); 64 max_d[u] = s[0] + 1; 65 if (ans2[ff][0].y == u) 66 ss[u] = max(ss[u], ans2[ff][1].x); 67 else 68 ss[u] = max(ss[u], ans2[ff][0].x); 69 ans[u] = max(ss[u], ans1[u]); 70 } 71 72 void pre_do(){ 73 M0(ss), M0(max_d); 74 for (int i = 0; i <= n; ++i){ 75 len[i][0] = len[i][1] = len[i][2] = one; 76 ans2[i][0] = ans2[i][1] = zero; 77 } 78 } 79 80 void init(){ 81 scanf("%d", &n); 82 pre_do(); 83 for (int i = 0; i <= n; ++i) 84 e[i].clear(); 85 int u, v; 86 for (int i = 1; i < n; ++i){ 87 scanf("%d%d", &u, &v); 88 e[u].push_back(v); 89 e[v].push_back(u); 90 } 91 } 92 93 void bfs(int s, int &t, const int& other){ 94 queue<int> q; 95 M0(inq), M0(pre); 96 memset(dis, -1, sizeof(int) * (n+10)); 97 q.push(s), dis[s] = 0, inq[s] = 1; 98 int u, v; 99 while (!q.empty()){ 100 u = q.front(); 101 q.pop(); 102 for (int i = 0; i < (int)e[u].size(); ++i){ 103 v = e[u][i]; 104 if (v == other) continue; 105 if (!inq[v]) 106 dis[v] = dis[u] + 1, inq[v] = 1, q.push(v), pre[v] = u; 107 } 108 } 109 t = s; 110 for (int i = 1; i <= n; ++i) 111 if (dis[t] < dis[i]) t = i; 112 } 113 114 void solve(){ 115 M0(fa), M0(ans1); 116 bfs(); 117 for (int i = n; i >= 1; --i) 118 gao1(pos[i]); 119 for (int i = 2; i <= n; ++i) 120 gao2(pos[i]); 121 int rt = 2; 122 for (int i = 2; i <= n; ++i) 123 if (ans[rt] > ans[i]) rt = i; 124 // cout << rt << endl; 125 ans_len = ans[rt] / 2; 126 int x, y; 127 bfs(rt, x, fa[rt]); 128 bfs(x, y, fa[rt]); 129 int m = 0; 130 while (y) z[m++] = y, y = pre[y]; 131 ans_x = z[m/2]; 132 bfs(fa[rt], x, rt); 133 bfs(x, y, rt); 134 m = 0; 135 while (y) z[m++] = y, y = pre[y]; 136 ans_y = z[m/2]; 137 printf("%d %d %d ",ans_len, ans_x, ans_y); 138 139 } 140 141 int main(){ 142 int cas; 143 scanf("%d", &cas); 144 while (cas--){ 145 init(); 146 solve(); 147 } 148 }