感謝hzwer的點分治互測。
給定一棵有n個點的樹
詢問樹上距離為k的點對是否存在。
輸入格式:
n,m 接下來n-1條邊a,b,c描述a到b有一條長度為c的路徑
接下來m行每行詢問乙個k
輸出格式:
對於每個k每行輸出乙個答案,存在輸出「aye」,否則輸出」nay」(不包含引號)
輸入樣例#1:
複製
2 11 2 2
2
輸出樣例#1:
複製
aye
對於30%的資料n<=100
對於60%的資料n<=1000,m<=50
對於100%的資料n<=10000,m<=100,c<=1000,k<=10000000
比較常規的一道點分治【然而我又因為一些奇奇怪怪的錯誤調了半天】
先以重心為根,對每個子樹dfs統計到根的路徑長度,將這些長度丟進hash表裡【偷懶的我用了stl】,對於每個子樹,在丟進去之前,查詢之前子樹是否存在路徑 = k - d,存在則ok
之後往子樹重心分治
#include#include#include#include#include#define ll long long int#define rep(i,n) for (int i = 1; i <= (n); i++)
#define redge(u) for (int k = h[u]; k != -1; k = ed[k].nxt)
using namespace std;
const int maxn = 10005,maxm = 10000005,inf = 1000000000;
inline int rd()
while (c >= 48 && c <= 57)
return out * flag;
}int n,m,h[maxn],ne = 0,f[maxn],siz[maxn],rt = 0,sum,vis[maxn];
int d[maxn],id[maxn],k,cnt;
bool flag;
maph;
struct edgeed[maxm];
inline void build(int u,int v,int w); h[u] = ne++;
ed[ne] = (edge); h[v] = ne++;
}void getrt(int u,int f)
f[u] = max(f[u],sum - siz[u]);
if (f[u] < f[rt]) rt = u;
}void dfs(int u,int f)
}void solve(int u)
rep(i,cnt) h[d[id[i]]]++;
}redge(u) if (!vis[to = ed[k].to])
}int main()
return 0;
}
洛谷 P3806 模板 點分治1
this way 點分治模板 點分治解決的好像大部分是樹上路徑問題 網上模板有很多,我就不贅述了,大致思想就是找到樹的重心,然後o n 地求出路徑經過這個點的所有情況,之後再將樹以這個重心為基準分成多個子樹,再找到他們的重心,如此分治的去做。網上的 各不相同,我找了同集訓隊的人的寫法,用set維護每...
洛谷 P3806 模板 點分治1
洛谷傳送門 給定一棵有 nn 個點的樹,詢問樹上距離為 kk 的點對是否存在。第一行兩個數 n,mn,m。第 22 到第 nn 行,每行三個整數 u,v,wu,v,w,代表樹上存在一條連線 uu 和 vv 邊權為 ww 的路徑。接下來 mm 行,每行乙個整數 kk,代表一次詢問。對於每次詢問輸出一行...
洛谷 P3806 模板 點分治1
感謝hzwer的點分治互測。給定一棵有n個點的樹 詢問樹上距離為k的點對是否存在。輸入格式 n,m 接下來n 1條邊a,b,c描述a到b有一條長度為c的路徑 接下來m行每行詢問乙個k 輸出格式 對於每個k每行輸出乙個答案,存在輸出 aye 否則輸出 nay 不包含引號 輸入樣例 1 複製2 1 1 ...