樹的重心維護 動態樹 資源運輸

2021-06-16 10:44:08 字數 1423 閱讀 3809

上交的寢室沒網實在是...據說acm時除錯只有5分鐘,基本上不用gdb,這點真是硬傷了,一般來說有難度的題目我要麼不除錯,要麼調比較久,看來有必要鍛鍊靜態除錯。

題意:一開始有n個點,每次可以選擇兩個點連邊,保證每次連邊後是乙個森林,對於每棵樹來說,要選擇乙個點,樹中其他點到它的距離和為此樹的權值,要求每次操作後,整個森林中的樹的權值和最小。

顯然每棵樹中要求的點是重心,因為考慮不是重心的時候,向重心移動,必定造成ans-n+2*size,如果不是重心,移動後ans會變小。

如果只是維護重心,其實簡單一點,兩顆樹i,j相連(均以重心x,y為根),新重心必定在兩重心的連線上,假設以y為根,對於x-y上的點z,如果它是重心,那麼z子樹以外的節點個數必定是對於子樹大小的維護,因為涉及到旋轉換根這種操作,所以不能直接統計,但是我們對於每個節點統計虛邊子樹大小的話,這個權值是不會隨著splay的形態改變而改變的,因此與splay子樹大小一起,還是可以求出子樹大小的。這樣一來在splay上走一下應該可以在o(nlogn)的時間解決重心的維護問題。

可是題目還要求每個點到重心的距離和,這種東西與子樹大小一樣,是不能直接在splay上統計的,同樣要用到虛邊資訊,麻煩的是,這個東西比子樹大小的限制更多,如果不是在特殊的節點還不能隨便求出,因此,考慮到兩棵樹相連頂多移動其中一棵樹大小次,這裡用啟發式來做一下,每次再用動態樹維護,當然,為了應付換根,還要處理一下,op記到頭的答案,ed記到尾的答案,演算法複雜度是o(nlognlogn)的,雖然題解中是o(nlogn)的,但是**長至8kb,最後4個點沒過,已經過了的點又比我跑得慢。

順便提一下,用啟發式就沒有了二分時候的等於號取不取的麻煩問題...

#include #include #include #include #include const int oo=1073741819,maxn=50000;

using namespace std;

int l[maxn],r[maxn],rt[maxn],c[maxn][2],size[maxn],b[maxn],g[maxn],f[maxn],op[maxn],ed[maxn],sum[maxn],tot[maxn],sw[maxn],t[maxn];

int e,n,m,ans;

int find(int x)

void swap(int x)

void updata(int x)

void pushdown(int x)

updata(x);

}void left(int x)

void right(int x)

void splay(int x)

else

} updata(x);

}void access(int x)

}int ask(int x,int &root,int n,int oroot)

}return 0;

}

ACM 樹重心的性質及動態維護

本文 求樹重心的方法 nlogn 還記得曾經提到過的樹的 重心 嗎?重心的定義是 以這個點為根,那麼所有的子樹 不算整個樹自身 的大小都不超過整個樹大小的一半。樹的重心的乙個的性質 樹中所有點到某個點的距離和中,到重心的距離和是最小的 如果有兩個重心,那麼他們的距離和一樣。這也是 道路修建 帶來的啟...

樹的重心 樹的直徑

樹的重心 樹的重心定義為 找到乙個點,其所有的子樹中最大的子樹節點數最少,那麼這個點就是這棵樹的重心,刪去重心後,生成的多棵樹盡可能平衡.實際上樹的重心在樹的點分治中有重要的作用,可以避免n 2的極端複雜度 從退化鏈的一端出發 保證nlogn的複雜度,利用樹型dp可以很好地求樹的重心.求樹的重心 模...

樹的直徑 樹的重心

樹的直徑 定義 那麼樹上最遠的兩個點,他們之間的距離,就被稱之為樹的直徑。樹的直徑的性質 1.直徑兩端點一定是兩個葉子節點。2.距離任意點最遠的點一定是直徑的乙個端點,這個基於貪心求直徑方法的正確性 可以得出。3.對於兩棵樹,如果第一棵樹直徑兩端點為 u,v 第二棵樹直徑兩端點為 x,y 用條邊將兩...