[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] 直径的主要内容,如果未能解决你的问题,请参考以下文章

XSY2968线性代数

TOJ 1545Hurdles of 110m(背包题)

XSY3209RGB Sequence

从C#使用COM属性时出现错误CS1545

xsy1529小Q与进位制 - 分治FFT

Timus 1545. Hieroglyphs Trie的即学即用 实现字典提示功能