[XSY 1545] 直径
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[XSY 1545] 直径相关的知识,希望对你有一定的参考价值。
题意
给定一棵 n 个点的树, 这棵树以 1 为根.
我们以这棵树为模板, 进行 m 次复制, 依次将子树 r[1], r[2], ..., r[m] 复制.
我们对这 m 棵子树连接 m-1 条边, 形成一棵新树.
求新树的直径.
n, m <= 300000 .
分析
对每棵子树求树的直径.
对于每次复制, 以 [ 根, 子树中直径的两个端点, 连接点 ] 建立虚树.
求树的直径.
实现
1 #include <cstdio> 2 #include <cstring> 3 #include <cstdlib> 4 #include <cctype> 5 #include <algorithm> 6 #include <vector> 7 #include <map> 8 using namespace std; 9 #define F(i, a, b) for (register int i = (a); i <= (b); i++) 10 #define LL long long 11 inline int rd(void) { 12 int f = 1; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == ‘-‘) f = -1; 13 int x = 0; for (; isdigit(c); c = getchar()) x = x*10+c-‘0‘; return x*f; 14 } 15 16 const int N = 300005; 17 const int L = 700000; // N * 2 while building the Virtual Tree 18 const int S = 5000000; // N * 3 + M * 2 19 20 int n, m; 21 vector<int> g[N]; 22 23 int siz[N], son[N], dep[N], par[N]; 24 int idx, dfn[N], top[N], last[N]; 25 26 void Son(int x) { 27 siz[x] = 1; 28 for (vector<int>::iterator it = g[x].begin(); it != g[x].end(); it++) 29 if (*it != par[x]) { 30 dep[*it] = dep[x] + 1, par[*it] = x; 31 Son(*it); 32 siz[x] += siz[*it]; 33 if (siz[son[x]] < siz[*it]) son[x] = *it; 34 } 35 } 36 void Split(int x, int anc) { 37 dfn[x] = ++idx, top[x] = anc; 38 if (son[x] > 0) Split(son[x], anc); 39 for (vector<int>::iterator it = g[x].begin(); it != g[x].end(); it++) 40 if (*it != par[x] && *it != son[x]) Split(*it, *it); 41 last[x] = idx; 42 } 43 44 inline int LCA(int x, int y) { 45 while (top[x] != top[y]) 46 dep[top[x]] > dep[top[y]] ? x = par[top[x]] : y = par[top[y]]; 47 return dep[x] < dep[y] ? x : y; 48 } 49 inline int Dist(int x, int y) { return dep[x] + dep[y] - 2 * dep[LCA(x, y)]; } 50 51 struct Meter { 52 int x, y, d; 53 friend inline bool operator < (Meter A, Meter B) { return A.d < B.d; } 54 }dia[N]; 55 56 inline void Union(Meter &A, Meter B) { 57 // binom(4, 2) = 6 58 Meter tmp = max(A, B); 59 tmp = max(tmp, (Meter){A.x, B.x, Dist(A.x, B.x)}); 60 tmp = max(tmp, (Meter){A.x, B.y, Dist(A.x, B.y)}); 61 tmp = max(tmp, (Meter){A.y, B.x, Dist(A.y, B.x)}); 62 A = max(tmp, (Meter){A.y, B.y, Dist(A.y, B.y)}); 63 } 64 void DP(int x) { 65 dia[x] = (Meter){x, x, 0}; 66 for (vector<int>::iterator it = g[x].begin(); it != g[x].end(); it++) 67 if (*it != par[x]) { 68 DP(*it); 69 Union(dia[x], dia[*it]); 70 } 71 } 72 73 vector<int> Node[N]; 74 int ed[N][4]; 75 76 int List[L], cnt; 77 int s[L], Len; 78 79 map<int, int> ID[N]; int tot; 80 struct Edge { int v, d; }; vector<Edge> G[S]; 81 82 inline void Init(int u, int v, int d) { 83 G[u].push_back((Edge){v, d}); 84 G[v].push_back((Edge){u, d}); 85 } 86 87 inline bool cmp(int i, int j) { return dfn[i] < dfn[j]; } 88 inline bool In(int x, int y) { return dfn[y] <= dfn[x] && last[x] <= last[y]; } 89 // x in subtree(y) 90 void Build(int id) { 91 cnt = 0; 92 for (vector<int>::iterator it = Node[id].begin(); it != Node[id].end(); it++) 93 List[++cnt] = *it; 94 sort(List + 1, List + cnt + 1, cmp); 95 cnt = unique(List + 1, List + cnt + 1) - List - 1; 96 97 int tmp = cnt; 98 F(i, 1, tmp-1) 99 List[++cnt] = LCA(List[i], List[i+1]); 100 sort(List + 1, List + cnt + 1, cmp); 101 cnt = unique(List + 1, List + cnt + 1) - List - 1; 102 103 int cur = tot; 104 F(i, 1, cnt) ID[id][List[i]] = ++tot; 105 // ID[id][List[i]] = cur + i 106 // O(log n) O(1) 107 108 Len = 0; 109 F(i, 1, cnt) { 110 while (Len > 0 && !In(List[i], List[s[Len]])) 111 s[Len--] = 0; 112 if (Len > 0) 113 Init(cur + s[Len], cur + i, dep[List[i]] - dep[List[s[Len]]]); 114 s[++Len] = i; 115 } 116 } 117 118 LL dis[S]; 119 void Expand(int x, int par) { 120 for (vector<Edge>::iterator it = G[x].begin(); it != G[x].end(); it++) 121 if (it->v != par) { 122 dis[it->v] = dis[x] + it->d; 123 Expand(it->v, x); 124 } 125 } 126 127 int main(void) { 128 #ifndef ONLINE_JUDGE 129 freopen("diameter.in", "r", stdin); 130 #endif 131 132 n = rd(), m = rd(); 133 F(i, 1, n-1) { 134 int x = rd(), y = rd(); 135 g[x].push_back(y), g[y].push_back(x); 136 } 137 138 Son(1); 139 Split(1, 1); 140 141 DP(1); 142 143 F(i, 1, m) { 144 int ri = rd(); 145 Node[i].push_back(ri), Node[i].push_back(dia[ri].x), Node[i].push_back(dia[ri].y); 146 } 147 F(i, 1, m-1) { 148 int a = rd(), b = rd(), c = rd(), d = rd(); 149 ed[i][0] = a, ed[i][1] = b, ed[i][2] = c, ed[i][3] = d; 150 Node[a].push_back(b), Node[c].push_back(d); 151 } 152 153 F(i, 1, m) 154 Build(i); 155 F(i, 1, m-1) { 156 int a = ed[i][0], b = ed[i][1], c = ed[i][2], d = ed[i][3]; 157 Init(ID[a][b], ID[c][d], 1); 158 } 159 160 Expand(1, -1); 161 int ID = max_element(dis+1, dis+tot+1) - dis; 162 dis[ID] = 0, Expand(ID, -1); 163 printf("%lld\n", *max_element(dis+1, dis+tot+1) + 1); 164 165 return 0; 166 }
以上是关于[XSY 1545] 直径的主要内容,如果未能解决你的问题,请参考以下文章