模板 點分治

2022-07-22 17:12:13 字數 1803 閱讀 1012

poj-1741

#include #include using namespace std;

const int n = 10010;

const int inf = 0x3f3f3f3f;

int n, k, ans;

int head[n], nxt[2 * n], to[2 * n], w[2 * n], tot; //鏈式前向星

void add_edge(int x, int y, int z)

bool vis[n];

int root, tsiz, siz[n], mx[n];

int arr[n], cnt;

void init()

void getroot(int u, int fa)

mx[u] = max(mx[u], tsiz - siz[u]);

if (mx[root] > mx[u]) root = u;

}}void getdis(int u, int d, int fa)

}int calc(int u, int d)

return sum;

}void dac(int u)

}} //此法時間複雜度不會退化

int main()

getroot(1, 0);

dac(root);

printf("%d\n", ans - n); //去除(u, u)點對

}return 0;

}

luogu_p3806

#include #include #include using namespace std;

const int n = 10010;

const int inf = 0x3f3f3f3f;

int n, m;

int query[n];

bool vis[n], ok[n];

int e_cnt, head[n], mx[n], sz[n], root, cnt, a[n], b[n], d[n];

/* 記當前分治的根為root

a記錄從root能到的點

d記錄a_i到root的距離

b記錄a_i屬於root的哪乙個子樹(當b[a[i]] == b[a[j]]時,說明a_i與a_j屬於root的同一顆子樹

*/struct edge

edge[n << 1];

void add_edge(int x, int y, int z)

void getroot(int u, int fa, int total)

mx[u] = max(mx[u], total - sz[u]);

if (mx[u] < mx[root]) root = u;

}void getdis(int u, int fa, int dis, int from)

}bool cmp(int x, int y)

void calc(int u)

sort(a + 1, a + 1 + cnt, cmp);

for (int i = 1; i <= m; i++)

else }}

}void dac(int u)

}int main()

for (int i = 1; i <= m; i++)

mx[0] = inf;

getroot(1, 0, n);

dac(root);

for (int i = 1; i <= m; i++)

}

點分治模板

luogu 3806 近些日子學了點分治,當然只是學了個模板。所謂點分治,使用於處理樹上路徑的一種分治手段。因為利用了重心的性質,時間複雜度可以保證呢。所謂演算法流程 選取當前子樹的重心 計算路徑總數,不管路徑是否過當前重心 後面會去重 計算起點和終點在同一顆子樹中的合法路徑 因為這條路徑不是簡單路...

點分治模板

這兩天跟著學了一手樹上點分治模板,然後有一些感悟,決定來寫一發部落格.首先,鑑於鄙人的經驗,如果想要較快速地學習乙個新演算法,肯定還是先看一道經典的例題比較好,所以我們先來一道例題.給你一棵tree,以及這棵樹上邊的距離.問有多少對點它們兩者間的距離小於等於k 輸入格式 n n 40000 接下來n...

點分治模板

bzoj1316 由於之前板子寫得太爛了,今天把它重新整理改進了一下 vis表示每個點是否已經當過根,所以注意dfs,findroot函式的計算過程中是不會對vis進行修改的 修改時只需要考慮對dfs和solve中的有關位置進行修改即可,其它部分基本不變 include using namespac...