題目:
題意:給定一棵樹,有n個點和n - 1條邊,邊有邊權,給出乙個k,求樹上任意兩點間的最短距離不大於k的個數
思路:看了09年漆子超的**,利用分治法,每次找樹的重心,重心即是在當前樹中刪掉此點後,節點數最多的子樹的節點數最小,找到重心後,求其所有子孫到其的距離,然後統計一下兩兩之和不大於k的個數,另外在統計過程中,會把在同一分支中的兩點也計算了,即這兩點間的路徑不經過重心,這明顯是多餘的,所以要減掉
總結:樹上的演算法真是巧妙啊。。。
#include #include #include #include using namespace std;
const int n = 10010;
struct edge
g[n*2];
int head[n], siz[n], sonsiz[n], dis[n];
bool vis[n];
int n, k, root, res, tmp, num, cnt;
void add_edge(int v, int u, int val)
void dfssiz(int v, int fa) /*處理以v點為根的樹的節點個數和v的子樹中節點最多的子樹節點數*/
}}void dfsroot(int r, int v, int fa) /*尋找重心*/
}void dfsdis(int v, int d, int fa) /*計算重心到每個子孫的距離*/
}int calc(int v, int d)
return ans;
}void dfs(int v)
}}int main()
dfs(1);
printf("%d\n", res);
}return 0;
}
poj 1741 Tree 樹的分治
解 文中有,就是把路徑分成經過樹根,和不經過樹根兩類,每次處理經過樹根的,然後剩下的子樹部分可以遞迴處理,如果每次選取樹的重心,那麼可以保證最多遞迴logn層。經過樹根的先排序,然後o n 的複雜度就能算出,那麼每層的複雜度nlogn,最多遞迴logn層,總複雜度nlogn 2 include in...
poj 1741 Tree 樹的分治
求樹上倆結點之間距離小於k的結點對個數 倆個點a,b的公共祖先為c,那麼這倆個點的距離就可以用dis a,c dis b,c 表示,我們可以不斷的處理這樣c,然後計算距離,處理點對,為了使平均效能最好,我們需要找的c為每一棵子樹的重心 需要注意的算點對的時候這種方法成立的條件是倆個點不在同一顆子樹上...
POJ 1741 Tree (樹的分治)
給定一棵樹,計算長度不超過 k的鏈的個數 樹分治入門題,看著題解刷的 選定乙個點,首先一條鏈要麼在此點的子樹上 要麼這條鏈經過這個點 在子樹上就可以劃分為子問題,然後分治處理 經過這個點的鏈,可以把子樹上的點到根的距離處理出來 然後對這些距離排個序,就能 o n 統計 選點要選重心,重心的所有子樹大...