樹中點對距離

2021-07-09 06:41:10 字數 1272 閱讀 5315

在一顆n個結點的樹上,統計有多少點對最短距離<=m。(點對不存在順序性)n<=10000

我們選取乙個點x作根,那麼任何點對都分成兩種型別

1、經過x

2、不經過x

我們對經過x的進行統計,對於不經過x的繼續在x的子樹中分治下去。這就是點分治。

我們處理出每個點的深度,排序後就很容易統計經過x的個數。

不過有可能出現一對點對的lca是y而不是x,然後他們被統計進去了,要在往下分治的過程中減去他們。

為了使分治樹不退化,每次選取重心充當根,那麼最多log n層,每一層點總和不超過n,複雜度為n log n。

#include

#include

#define fo(i,a,b) for(i=a;i<=b;i++)

#define fd(i,a,b) for(i=a;i>=b;i--)

using namespace std;

const int maxn=10000+10;

int d[maxn],s[maxn],h[maxn],go[maxn*2],next[maxn*2],dis[maxn*2],a[maxn];

bool bz[maxn];

int i,j,k,l,t,n,m,tot,ans,top;

void add(int

x,int

y,int z)

void dfs(int

x,int

y) t=next[t];

}}void dg(int

x,int

y) t=next[t];

}}bool cmp(int

x,int

y)void solve(int

x) if (i==j) i--;

ans-=i;}}

j=x;k=0;

while (1)

t=next[t];

}if (!t) break;

}d[j]=0;

dg(j,0);

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

i=0;k=j;

fd(j,top,1)

if (i==j) i--;

ans+=i;

}t=h[k];

bz[k]=1;

while (t)

}int main()

solve(1);

printf("%d\n",ans);

}

樹中點對距離(點分治)

給出一棵帶邊權的樹,問有多少對點的距離 len 這是一道點分治的經典題目,可以給點分治的初學者練手。點分治,顧名思義就是把每個點分開了處理答案。假設,目前做到了以x為根的子樹。先求出子樹中每個點到根的距離di s 對於兩個點 i 和 j,如果di si d isj k 那麼 i j 就是乙個合法的點...

點分治模板 (樹中點對距離)

點分治就是在一棵樹中,將每個點分治 基本概念 點分治 將一棵無根樹變成有根樹,再分別處理每棵有根子樹。重心 在一棵樹中,這個點的最大子樹是所有點中最小的。也可以說是刪除該點時,樹內剩下的子樹最大節點數最小。size i 表示以i為根的子樹節點數量。如何求重心?求出size,什麼是定義,就怎麼求。一般...

JZOJ 1166 樹中點對距離

給出一棵帶邊權的樹,問有多少對點的距離 le n 2 n 10000 len 231 這是一道十分經典的點分治題目。點分治,顧名思義,就是按照點來分治。假設當前要計算某棵子樹裡面滿足題目條件的點對數,我們可以先找出這棵子樹的重心。易知,此棵子樹的點對數 經過重心的合法點對數 不經過重心的合法點對數。...