關於樹的重心有一條性質,假如\(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...