P4178 Tree
生活随笔
收集整理的這篇文章主要介紹了
P4178 Tree
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
P4178 Tree
題意:
給定一棵 n 個(gè)節(jié)點(diǎn)的樹,每條邊有邊權(quán),求出樹上兩點(diǎn)距離小于等于 k 的點(diǎn)對(duì)數(shù)量。
題解:
點(diǎn)分治的模板題是求等于K的路徑條數(shù)
本題是求小于等于K的路徑條數(shù),我們只需要改變統(tǒng)計(jì)答案即可
原本統(tǒng)計(jì)答案是對(duì)一個(gè)路勁長(zhǎng)度len,判斷K-len在之前的子樹中出現(xiàn)多少次,用f數(shù)組來(lái)記錄,直接查看f[k-len]等于多少即可
現(xiàn)在統(tǒng)計(jì)答案是對(duì)一個(gè)路徑長(zhǎng)度len,判斷小于等于K-len的數(shù)在之前的子樹中出現(xiàn)多少次,統(tǒng)計(jì)區(qū)間數(shù)量,我們可以用樹狀數(shù)組來(lái)實(shí)現(xiàn),對(duì)于每個(gè)len我們插入數(shù)組f[]其中,然后求1~K-len的區(qū)間查詢
代碼:
詳細(xì)看代碼
#include<bits/stdc++.h> #define MAXN 40005 #define MAXK 20005 using namespace std;int N,K;struct edge{int v,w;edge(int v=0, int w=0):v(v), w(w){} };vector<edge> adj[MAXN];// int fw[MAXK]; int lbt(int x){return x & (-x); } int getsum(int x){int ans = 0;for(;x>0;x-=lbt(x)){ans += fw[x];}return ans; }void change(int x, int dv){for(;x<=K;x+=lbt(x)){fw[x] += dv;} }// int sz[MAXN]; bool vis[MAXN]; int rt; void dfs_rt(int u, int fa, int tot){//O(tot)求根 sz[u] = 1;int v, n = 0;for(int k=0;k<adj[u].size();k++){v = adj[u][k].v;if(v==fa || vis[v]) continue;dfs_rt(v, u, tot);sz[u] += sz[v];n = max(n, sz[v]);}n = max(n, tot-sz[u]);if(n*2 <= tot) rt = u; }void dfs_sz(int u, int fa){//O(tot)求子樹sz[u] = 1;int v, n = 0;for(int k=0;k<adj[u].size();k++){v = adj[u][k].v;if(v==fa || vis[v]) continue;dfs_sz(v, u);sz[u] += sz[v];} }int d[MAXN], cnt = 0; void dfs_dis(int u, int fa, int dis){//O(tot)d[++cnt] = dis;//記錄距離 int v,w;for(int k=0;k<adj[u].size();k++){v = adj[u][k].v;w = adj[u][k].w;if(v==fa || vis[v]) continue;dfs_dis(v, u, dis + w);} }void dfs_clear(int u, int fa, int dis){//O(tot)清零 if(dis) change(dis, -1);int v,w;for(int k=0;k<adj[u].size();k++){v = adj[u][k].v;w = adj[u][k].w;if(v==fa || vis[v]) continue;dfs_clear(v, u, dis + w);} }int work(int u, int tot){ dfs_rt(u, 0, tot);u = rt;dfs_sz(u, 0);vis[u] = 1;int v,w;//solve/*求出每個(gè)點(diǎn)到根節(jié)點(diǎn)的距離,然后記錄到數(shù)組d然后對(duì)于d[i],查詢0~K-d[i]區(qū)間大小,用樹狀數(shù)組實(shí)現(xiàn) 如果d[i]<=K,那么d[i]本身也符合條件 將數(shù)組d插入到樹狀數(shù)組當(dāng)以一個(gè)點(diǎn)為根的一輪結(jié)束時(shí)記得情況數(shù)組樹狀數(shù)組 */ int ans = 0;for(int k=0;k<adj[u].size();k++){v = adj[u][k].v;w = adj[u][k].w;if(vis[v]) continue;cnt = 0;dfs_dis(v, u, w);for(int i=1;i<=cnt;i++){if(d[i] <= K) ++ans;ans += getsum(max(0,K-d[i]));}for(int i=1;i<=cnt;i++){change(d[i], +1);}}dfs_clear(u,0,0);//手動(dòng)清空 //for(int k=0;k<adj[u].size();k++){v = adj[u][k].v;//w = adj[u][k].w;if(vis[v]) continue;ans += work(v,sz[v]);} return ans; }int main(){cin>>N;int u,v,w;for(int i=1;i<N;i++){cin>>u>>v>>w;adj[u].push_back(edge(v,w));adj[v].push_back(edge(u,w));}cin>>K;cout<<work(1, N)<<endl;return 0; }總結(jié)
以上是生活随笔為你收集整理的P4178 Tree的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Filebeat日志收集器
- 下一篇: Infinite Tree