3611: [Heoi2014]大工程
Time Limit: 60 Sec Memory Limit: 512 MBSubmit: 1101 Solved: 478
[Submit][Status][Discuss]
Description
国家有一个大工程,要给一个非常大的交通网络里建一些新的通道。
我们这个国家位置非常特殊,可以看成是一个单位边权的树,城市位于顶点上。
在 2 个国家 a,b 之间建一条新通道需要的代价为树上 a,b 的最短路径。
现在国家有很多个计划,每个计划都是这样,我们选中了 k 个点,然后在它们两两之间 新建 C(k,2)条 新通道。
现在对于每个计划,我们想知道:
1.这些新通道的代价和
2.这些新通道中代价最小的是多少
3.这些新通道中代价最大的是多少
Input
第一行 n 表示点数。
接下来 n-1 行,每行两个数 a,b 表示 a 和 b 之间有一条边。
点从 1 开始标号。 接下来一行 q 表示计划数。
对每个计划有 2 行,第一行 k 表示这个计划选中了几个点。
第二行用空格隔开的 k 个互不相同的数表示选了哪 k 个点。
Output
输出 q 行,每行三个数分别表示代价和,最小代价,最大代价。
Sample Input
10
2 1
3 2
4 1
5 2
6 4
7 5
8 6
9 7
10 9
5
2
5 4
2
10 4
2
5 2
2
6 1
2
6 1
2 1
3 2
4 1
5 2
6 4
7 5
8 6
9 7
10 9
5
2
5 4
2
10 4
2
5 2
2
6 1
2
6 1
Sample Output
3 3 3
6 6 6
1 1 1
2 2 2
2 2 2
6 6 6
1 1 1
2 2 2
2 2 2
HINT
n<=1000000
q<=50000并且保证所有k之和<=2*n
Source
建出虚树,树形DP
1 #include <bits/stdc++.h> 2 3 namespace scanner 4 { 5 inline char nextChar(void) 6 { 7 static const int siz = 1 << 20; 8 9 static char buf[siz]; 10 static char *hd = buf + siz; 11 static char *tl = buf + siz; 12 13 if (hd == tl) 14 fread(hd = buf, 1, siz, stdin); 15 16 return *hd++; 17 } 18 19 inline int nextInt(void) 20 { 21 register int ret = 0; 22 register bool neg = false; 23 register char bit = nextChar(); 24 25 for (; bit < 48; bit = nextChar()) 26 if (bit == '-')neg ^= true; 27 28 for (; bit > 47; bit = nextChar()) 29 ret = ret * 10 + bit - '0'; 30 31 return neg ? -ret : ret; 32 } 33 } 34 35 const int inf = 1e9; 36 37 const int maxn = 2000005; 38 const int maxm = 5000005; 39 40 struct graph 41 { 42 int hd[maxn], to[maxm], nt[maxm], tot; 43 44 inline graph(void) 45 { 46 tot = top = 0; 47 memset(hd, 0, sizeof(hd)); 48 memset(marked, 0, sizeof(marked)); 49 } 50 51 inline void addEdge(int x, int y) 52 { 53 nt[++tot] = hd[x]; to[tot] = y; hd[x] = tot; 54 nt[++tot] = hd[y]; to[tot] = x; hd[y] = tot; 55 56 markPoint(x); 57 markPoint(y); 58 } 59 60 int used[maxn], marked[maxn], top; 61 62 inline void markPoint(int t) 63 { 64 if (!marked[t])used[++top] = t, marked[t] = true; 65 } 66 67 inline void recovery(void) 68 { 69 while (top) 70 { 71 int t = used[top--]; 72 marked[t] = false; 73 hd[t] = 0; 74 } 75 } 76 }; 77 78 struct boolean 79 { 80 bool s[maxn]; 81 82 inline boolean(void) 83 { 84 top = 0; 85 memset(s, 0, sizeof(s)); 86 memset(marked, 0, sizeof(marked)); 87 } 88 89 inline void mark(int t) 90 { 91 s[t] = true; 92 93 markPoint(t); 94 } 95 96 int used[maxn], marked[maxn], top; 97 98 inline void markPoint(int t) 99 { 100 if (!marked[t])used[++top] = t, marked[t] = true; 101 } 102 103 inline void recovery(void) 104 { 105 while (top) 106 { 107 int t = used[top--]; 108 marked[t] = false; 109 s[t] = false; 110 } 111 } 112 113 inline bool operator [] (int t) 114 { 115 return s[t]; 116 } 117 }; 118 119 int n, m; 120 121 graph src; 122 graph use; 123 124 int dfn[maxn], dep[maxn], fa[maxn][21]; 125 126 void preworkDfs(graph &g, int u, int f) 127 { 128 static int tim = 0; 129 130 dfn[u] = ++tim; 131 dep[u] = dep[f] + 1; 132 133 fa[u][0] = f; 134 135 for (int i = 1; i <= 20; ++i) 136 fa[u][i] = fa[fa[u][i - 1]][i - 1]; 137 138 for (int i = g.hd[u]; i; i = g.nt[i]) 139 if (f != g.to[i])preworkDfs(g, g.to[i], u); 140 } 141 142 inline int getLca(int a, int b) 143 { 144 if (dep[a] < dep[b]) 145 a ^= b ^= a ^= b; 146 147 for (int i = 20; ~i; --i) 148 if (dep[fa[a][i]] >= dep[b]) 149 a = fa[a][i]; 150 151 if (a == b)return a; 152 153 for (int i = 20; ~i; --i) 154 if (fa[a][i] != fa[b][i]) 155 a = fa[a][i], 156 b = fa[b][i]; 157 158 return fa[a][0]; 159 } 160 161 inline bool cmpDfn(int a, int b) 162 { 163 return dfn[a] < dfn[b]; 164 } 165 166 boolean mrk; 167 168 struct stack 169 { 170 int s[maxn], tot; 171 172 inline void push(int t) 173 { 174 s[++tot] = t; 175 } 176 177 inline void pop(void) 178 { 179 if (tot)--tot; 180 } 181 182 inline int top(void) 183 { 184 return s[tot]; 185 } 186 187 inline int tat(void) 188 { 189 return s[tot - 1]; 190 } 191 192 inline int size(void) 193 { 194 return tot; 195 } 196 197 inline bool empty(void) 198 { 199 return tot == 0; 200 } 201 202 inline void clear(void) 203 { 204 tot = 0; 205 } 206 }; 207 208 stack stk; 209 210 typedef long long lnt; 211 212 struct answer 213 { 214 int maxi; 215 int mini; 216 217 inline void setup(void) 218 { 219 maxi = 0; 220 mini = inf; 221 } 222 223 inline void updateMin(int t) 224 { 225 if (mini > t) 226 mini = t; 227 } 228 229 inline void updateMax(int t) 230 { 231 if (maxi < t) 232 maxi = t; 233 } 234 }ans; 235 236 lnt all, dp[maxn], sz[maxn]; 237 238 int maxPath[maxn]; 239 int minPath[maxn]; 240 241 void getansDfs(graph &g, int u, int f) 242 { 243 dp[u] = 0LL; 244 sz[u] = mrk[u]; 245 maxPath[u] = 0; 246 minPath[u] = inf; 247 248 for (int i = g.hd[u]; i; i = g.nt[i]) 249 if (g.to[i] != f) 250 { 251 int v = g.to[i]; 252 int d = dep[v] - dep[u]; 253 254 getansDfs(g, v, u); 255 256 sz[u] += sz[v]; 257 dp[u] += dp[v]; 258 dp[u] += sz[v] * (all - sz[v]) * d; 259 260 ans.updateMin(minPath[v] + minPath[u] + d); 261 ans.updateMax(maxPath[v] + maxPath[u] + d); 262 263 if (minPath[u] > minPath[v] + d) 264 minPath[u] = minPath[v] + d; 265 266 if (maxPath[u] < maxPath[v] + d) 267 maxPath[u] = maxPath[v] + d; 268 } 269 270 if (mrk[u]) 271 { 272 ans.updateMin(minPath[u]); 273 ans.updateMax(maxPath[u]); 274 275 minPath[u] = 0; 276 } 277 } 278 279 signed main(void) 280 { 281 n = scanner::nextInt(); 282 283 for (int i = 1; i < n; ++i) 284 { 285 int x = scanner::nextInt(); 286 int y = scanner::nextInt(); 287 288 src.addEdge(x, y); 289 } 290 291 preworkDfs(src, 1, 0); 292 293 m = scanner::nextInt(); 294 295 while (m--) 296 { 297 static int k, p[maxn]; 298 299 k = scanner::nextInt(); 300 301 for (int i = 1; i <= k; ++i) 302 p[i] = scanner::nextInt(); 303 304 std::sort(p + 1, p + k + 1, cmpDfn); 305 306 use.recovery(); 307 mrk.recovery(); 308 309 ans.setup(); 310 stk.clear(); 311 312 all = k; 313 314 for (int i = 1; i <= k; ++i) 315 mrk.mark(p[i]); 316 317 for (int i = 1; i <= k; ++i) 318 { 319 if (!stk.empty()) 320 { 321 int t = getLca(p[i], stk.top()); 322 323 while (dfn[t] < dfn[stk.top()]) 324 { 325 if (dfn[t] >= dfn[stk.tat()]) 326 { 327 use.addEdge(t, stk.top()), stk.pop(); 328 329 if (stk.top() != t) 330 stk.push(t); 331 332 break; 333 } 334 335 use.addEdge(stk.top(), stk.tat()), stk.pop(); 336 } 337 } 338 339 stk.push(p[i]); 340 } 341 342 while (stk.size() > 1) 343 use.addEdge(stk.top(), stk.tat()), stk.pop(); 344 345 getansDfs(use, stk.top(), 0); 346 347 printf("%lld %d %d ", dp[stk.top()], ans.mini, ans.maxi); 348 } 349 }
@Author: YouSiki