感謝hzwer的點分治互測。
給定一棵有n個點的樹
詢問樹上距離為k的點對是否存在。
輸入格式:
n,m接下來n-1條邊a,b,c描述a到b有一條長度為c的路徑
接下來m行每行詢問乙個k
輸出格式:
對於每個k每行輸出乙個答案,存在輸出「aye」,否則輸出」nay」(不包含引號)
輸入樣例#1:
2 1輸出樣例#1:1 2 2
2
aye對於30%的資料n<=100
對於60%的資料n<=1000,m<=50
對於100%的資料n<=10000,m<=100,c<=10000,k<=10000000
對於每個點,分為有長度為k的路徑經過點以及長度為k的路徑在其子樹
對於長度為k的路徑在其子樹的點,我們可以將其看作是長度為k的路徑經過其子樹所在根節點
那麼這就是點分治的基本思想
為降低複雜度,我們每次採取重心作為根節點。將樹的深度將至logn
則複雜度為o(nlogn2)
#include#define inf 0x3f3f3f3fview codeusing
namespace
std;
const
int maxn=10000+100,maxm=10000000+100
;int
head[maxn];
intq[maxn],ans[maxn];
intp[maxm],t[maxn];
intd[maxn],dis[maxn],vis[maxn];
ints[maxn],ms[maxn];
int rt=0
,sum;
intn,m;
struct
edge
e[maxn
<<1
];int size=0
;inline
intread()
while(ch>='
0'&&ch<='9')
return x*f;
}void addedge(int u,int v,int
w)void tc(int u,int fa)//
樹的重心
ms[u]=max(ms[u],sum-ms[u]);
if(ms[u]u;
}void dfs(int u,int
fa)}
void cal(int
u)
for(int i=1;i<=tot;i++)
p[t[i]]=0;//
桶清空,用memsettle
}void solve(intu)}
intmain()
for(int i=1;i<=m;i++)
q[i]=read();
sum=n;ms[rt]=inf;
tc(1,0);
solve(rt);
for(int i=1;i<=m;i++)
puts(ans[i]?"
aye":"
nay"
);
return0;
}
P3806 模板 點分治1
給定一棵有 n 個點的樹,詢問樹上距離為 k 的點對是否存在。關於點分治具體內容可以看這個 這裡主要是詳細講講 getrt是用來求重心,我們利用樹型dp的思維來做,即找到該節點所有的子樹,找到最大的哪一顆即可 void getrt int u,int pa 求重心 maxp u max maxp u...
P3806 模板 點分治1
感謝hzwer的點分治互測。給定一棵有n個點的樹 詢問樹上距離為k的點對是否存在。輸入格式 n,m 接下來n 1條邊a,b,c描述a到b有一條長度為c的路徑 接下來m行每行詢問乙個k 輸出格式 對於每個k每行輸出乙個答案,存在輸出 aye 否則輸出 nay 不包含引號 輸入樣例 1 複製2 1 1 ...
P3806 模板 點分治1
p3806 模板 點分治1 定一棵有 n 個點的樹,多次詢問樹上距離為 k 的點對是否存在。澱粉質模板題。澱粉質的核心就是其只統計經過當前根結點的路徑,即可以把兩條路徑 拼 起來,同時分治結構保證了其只有 log 次這樣的計算。常用於統計樹上點對數量這樣的問題。來看這道題。可以對每乙個路徑長度開乙個...