題意:給定一棵樹(測試資料中樹的結點數中告知),求斷掉每條邊兩棵子樹所有重心的編號和之和。
題解:重心 + 樹狀陣列
先隨便求個重心出來,記做\(k\)。子樹大小記為\(sz\),子結點子樹大小的最大值記為\(mx\),考慮乙個結點\(u\not = k\):
首先,割掉一條邊使得\(u\)成為所在連通塊的重心,這條邊一定不在\(u\)子樹內。原因很簡單,考慮若\(u\)在\(k\)的\(v\)方向的子樹中,把\(u\)子樹中一條邊刪去後,\(sz[v]\)會減小,那麼重心\(k\)會往非\(v\)方向偏移或者不動,但絕不會進入\(v\)子樹。
然後再考慮刪去的子樹應滿足什麼條件。容易發現是否合法只與子樹大小有關:我們得保證與\(u\)相連的子樹都滿足大小不超過連通塊大小除以\(2\)這個條件。令\(s\)為刪去的子樹(與\(u\)不連通的子樹)大小,條件形式化即為:
\[2\times mx[u]\leq n-s\\
2\times(n-s-sz[u]) \leq n-s
\]解出
\[s \in[n - 2\times sz[u], n-2 \times mx[u]]
\]再補上條件,刪掉的邊不在\(u\)子樹中。
這個怎麼求呢?看起來可以無腦主席樹,但是有更好的做法:
一條邊\((u,fa[u])\),\(sz[u]\)對\(u\)子樹外有貢獻,\(n-sz[u]\)對\(u\)子樹內有貢獻,\(sz[u]\)對\(u\)的祖先結點有負的貢獻。
對於第乙個,把所有的貢獻加入樹狀陣列,到進入\(u\)的時候把貢獻去掉,離開\(u\)是把貢獻加上。
對於第二個,進入\(u\)的時候把貢獻加入,離開\(u\)是把貢獻去掉。
對於第三個,記錄進出\(u\)貢獻的增量,把
一、二的貢獻減去這個增量,就是\(u\)作為重心的次數。
最後考慮\(u=k\)的情況:
設最大兒子是\(v\),次大兒子是\(v'\),則可以分兩類:
dfs的時候記錄一下即可。
**皮了一下。
#include #include #include #define pb push_back
using namespace std;
typedef long long ll;
const int n = 3e5 + 5;
int n, rt, sz[n], mx[n], son1, son2;
vectorg[n];
ll ans;
struct bit
void clear()
void add(int u, int v)
}int qry(int u)
return ans;
}int qry(int l, int r)
} *b1 = new bit, *b2 = new bit;
void dfs(int u, int fa = 0)
if(n - sz[u] > n / 2) tg = 0;
if(tg && !rt) rt = u;
}bool s1[n];
void dfs2(int u, int fa = 0)
for(int i = 0; i < (int) g[u].size(); i ++)
if(u != rt)
}int main()
rt = 0; dfs(1); dfs(rt);
ans = 0;
for(int i = 1; i <= n; i ++) if(i != rt)
son1 = son2 = 0;
for(int i = 0; i < (int) g[rt].size(); i ++) else if(sz[v] > sz[son2])
}dfs2(rt);
printf("%lld\n", ans);
b1->clear(); b2->clear();
}return 0;
}
CSP S2019 D2T3 樹的重心
小簡單正在學習離散數學,今天的內容是圖論基礎,在課上他做了如下兩條筆記 乙個大小為 n nn 的樹由 n nn 個結點與 n 1 n 1 n 1 條無向邊構成,且滿足任意兩個結點間有且僅有一條簡單路徑。在樹中刪去乙個結點及與它關聯的邊,樹將 為若干個子樹 而在樹中刪去一條邊 保留關聯結點,下同 樹將...
CSP2019 樹的重心(樹的重心 倍增 換根)
當年我做這道題時還太嫩了,只能想到暴力。其實如果會了更高的科技這道題只要稍微對暴力優化一下就能ac 我也不會含淚75pts了 廢話不說了,暴力的思路就是列舉每一條邊然後求兩個子樹的重心。直接求重心的複雜度是 o n 的,我們考慮優化到 o log 我們想要求以 x 為根的子樹的重心,首先有個引理 這...
CSP2019樹的重心
題解 csp2019d2t3 首先我們要明確乙個性質,那就是對於一棵樹的任何乙個節點來說,如果這個點不是重心,那麼這棵樹的重心就一定在這個節點的以重兒子為根節點的子樹裡 證明顯而易見,因為該點不是重心所以siz 重兒子 一定大於 lfloor frac rfloor 另外還有乙個重心的定義 重心所有...