洛谷 P5666 樹的重心

2022-09-11 02:06:12 字數 1271 閱讀 5204

關於樹的重心有一條性質,假如\(u\)不是重心,那麼重心一定在\(u\)的size最大的子樹中.

利用這個性質我們可以利用倍增的思想快速找到重心.即維護\(jump(u,i)\)表示從\(u\)出發,向重兒子走\(2^i\)步所到達的節點.

由於要對於每條邊統計,所以用換根dp的思想,在dfs的時候維護以當前節點為根時的\(jump\)等資訊即可.

#include #include #include #include #define debug(...) fprintf(stderr,__va_args__)

using namespace std;

inline char nc()

templatevoid read(t &x)

while(ch>='0'&&ch<='9')

x*=f;

}typedef long long ll;

const int maxn=299995+50;

int t,n;

int head[maxn];

int anc[maxn],siz[maxn],son[maxn][2];

int pre[maxn],s[maxn],jump[maxn][20];

ll an;

struct edge

}; vectorg;

inline void addedge(int u,int v)

void dfs0(int u)

pre[u]=anc[u],s[u]=siz[u],jump[u][0]=son[u][0];

for(int i=1;i<20;++i) jump[u][i]=jump[jump[u][i-1]][i-1];

}inline int check(int x,int r)

void sol(int u)

void dfs1(int u)

pre[u]=anc[u],s[u]=siz[u],jump[u][0]=son[u][0];

for(int i=1;i<20;++i) jump[u][i]=jump[jump[u][i-1]][i-1];

}int main()

an=0;

dfs0(1);

dfs1(1);

printf("%lld\n",an);

} return 0;

}

P5666 樹的重心題解

很容易打出乙個 o n 列舉邊 再 o n 求重心 的 o n 2 的演算法 期望得分 40 points 其實分析鏈和完美二叉樹可以與暴力一共拿到75分 正解 整體複雜度 o n log n 給出結論 結論 一棵以 x 為根的樹的重心,一定在 x 的重兒子所構成的集合中,而所有重兒子就構成了一條重...

洛谷 P1395 會議(樹的重心)

為什麼要找樹的重心呢?假設我們已經找到了樹的重心,如果把開會地點從重心向右移走,那麼對答案的貢獻就是 左邊的元素和 右邊的元素和。而因為是樹的重心,所以向右移走後左面的元素數量一定大於右面的元素數量,所以ans是比在重心的情況大的,所以最終我們選擇重心。include include include...

樹 洛谷 P1087 FBI樹

我們可以把由 0 和 1 組成的字串分為三類 全 0 串稱為b串,全 1 串稱為i串,既含 0 又含 1 的串則稱為f串。fbi樹是一種二叉樹,它的結點型別也包括f結點,b結點和i結點三種。由乙個長度為2 n的 01 串s可以構造出一棵fbi樹t,遞迴的構造方法如下 1 t的根結點為r,其型別與串s...