【清华集训2017】榕树之心
簡(jiǎn)要題意:(考慮到某些人搜題解只是懶得看題面)
特殊點(diǎn)從 \(1\) 號(hào)點(diǎn)出發(fā),每次選擇一個(gè)與當(dāng)前選擇連通塊相連的點(diǎn),加入連通塊,并且把我們的特殊點(diǎn)向那個(gè)選的點(diǎn)移動(dòng)一格。對(duì)每個(gè)點(diǎn)求是否能成為我們的特殊點(diǎn)的終點(diǎn)。\(1\) 處在一開始的連通塊之中。
不錯(cuò)的一道題。但是如果要很快地寫對(duì)需要冷靜思考(像我就不知道在干什么)。像我這樣的菜雞看了題解才會(huì)……
先考慮簡(jiǎn)單的部分,即 \(W = 3\),只輸出 \(1\) 的答案。
先根據(jù)特殊點(diǎn)的深度的奇偶性來(lái)判斷一個(gè)點(diǎn)有沒有可能(即 \(dep_x + n\) 的奇偶性)。
根據(jù)套路,如果有一個(gè)子樹的大小大于總大小的一半,那么那個(gè)子樹顯然能貢獻(xiàn)很多,但是不一定會(huì)無(wú)解。如果不存在,顯然能構(gòu)造出一個(gè)方案(即分成三部分,一個(gè)部分里只有一個(gè),另外兩個(gè)部分大小分別都小于一半,顯然有解)。
所以現(xiàn)在只要考慮那個(gè)最大的子樹,如果我們把它消的小了,那么還是有可能的。記 \(f_i\) 為向 \(i\) 走能造成的最小的相對(duì)深度(不是相對(duì) \(i\) 而是相對(duì)走到 \(i\) 的那個(gè)點(diǎn),即 \(i\) 也會(huì)對(duì)這個(gè)深度產(chǎn)生貢獻(xiàn)。這樣做能方便各種地方的細(xì)節(jié))。
顯然,考慮如果 \(u\) 向 最大的子樹 \(v\) 走,此時(shí)如果 \(sz_u - sz_v - 1\) 即其他子樹的大小是比 \(f_v\) 大的,又因?yàn)?\(sz_v > sz_u - sz_v - 1\),那么顯然能構(gòu)造出一種方案,使得 \(v\) 的貢獻(xiàn)與 \(sz_u - sz_v - 1\) 相差不超過(guò) \(1\) 。所以直接根據(jù)奇偶性進(jìn)行轉(zhuǎn)移,即 \(f_u = sz_u - 1 \mod 2\)。
但是如果這個(gè)比不上 \(f_v\) ,那么其他的子樹肯定是要拿去消 \(f_v\) 的,所以 \(f_u = f_v - (sz_u - sz_v - 1) + 1\)。
所以現(xiàn)在已經(jīng)做完這個(gè)簡(jiǎn)單的部分了。考慮其他點(diǎn)的情況。因?yàn)槁窂缴系狞c(diǎn)是必經(jīng)的,所以如果把這條路徑縮成一個(gè)點(diǎn),上述的過(guò)程依然能進(jìn)行。(因?yàn)槿绻c(diǎn)可行,那就是對(duì)消的,那么在鏈上顯然可以)
所以我們?nèi)跃S護(hù)那個(gè)最大的子樹。因?yàn)橐粭l鏈都縮成一個(gè)點(diǎn)了,那么這些子樹都是原樹某個(gè)點(diǎn)的子樹。因此不必要考慮換根DP的各種細(xì)節(jié),直接類似上面的過(guò)程處理下去即可。
注意數(shù)據(jù)的清空。同時(shí)因?yàn)樽兞砍跏蓟脑?#xff0c;以及轉(zhuǎn)移沒推清楚,先RE了一發(fā),又WA成45了一發(fā)。
#include <bits/stdc++.h>const int MAXN = 100010;int head[MAXN], nxt[MAXN << 1], to[MAXN << 1], tot; void addedge(int b, int e) {nxt[++tot] = head[b]; to[head[b] = tot] = e;nxt[++tot] = head[e]; to[head[e] = tot] = b; } int sz[MAXN], fir[MAXN], sec[MAXN]; int f[MAXN], ansl[MAXN], n; int cmp(int a, int b) { // a >= breturn sz[a] == sz[b] ? f[a] <= f[b] : sz[a] > sz[b]; } void gx(int & fir, int & sec, int v) {if (cmp(v, fir)) sec = fir, fir = v;else if (cmp(v, sec)) sec = v; } void dfs1(int u, int fa = 0) {sz[u] = 1;for (int i = head[u]; i; i = nxt[i])if (to[i] != fa) {dfs1(to[i], u);sz[u] += sz[to[i]];gx(fir[u], sec[u], to[i]);}if (!fir[u]) return ;int R = sz[u] - 1 - sz[fir[u]];if (R > f[fir[u]]) f[u] = sz[u] + 1 & 1; else f[u] = f[fir[u]] + 1 - R;// std::cout << u << ' ' << sz[u] << " : " << fir[u] << ' ' << sec[u] << " : " << f[u] << ' ' << R << std::endl; } void dfs2(int u, int fa = 0, int ma = 0, int dep = 0) {int t, v;gx(v = ma, t = 0, fir[u]);if (dep + n & 1)ansl[u] = n - dep - 1 - sz[v] >= f[v];for (int i = head[u]; i; i = nxt[i]) if (to[i] != fa) {gx(v = ma, t = 0, to[i] == fir[u] ? sec[u] : fir[u]);dfs2(to[i], u, v, dep + 1);} } int main() {// freopen("1.in", "r", stdin);std::ios_base::sync_with_stdio(false), std::cin.tie(0);int W, T; std::cin >> W >> T;while (T --> 0) {std::cin >> n;for (int i = 1, t1, t2; i < n; ++i) {std::cin >> t1 >> t2;addedge(t1, t2);}dfs1(1); dfs2(1);for (int i = 1; i <= (W == 3 ? 1 : n); ++i)std::cout << ansl[i];std::cout << '\n';memset(head, 0, n + 1 << 2); tot = 0;memset(ansl, 0, n + 1 << 2);memset(fir, 0, n + 1 << 2);memset(sec, 0, n + 1 << 2);memset(f, 0, n + 1 << 2);}return 0; }轉(zhuǎn)載于:https://www.cnblogs.com/daklqw/p/11574871.html
《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀總結(jié)
以上是生活随笔為你收集整理的【清华集训2017】榕树之心的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: legend3---4、lavarel中
- 下一篇: 后盾网lavarel视频项目---5、淘