感謝hzwer的點分治互測。
給定一棵有n個點的樹
詢問樹上距離為k的點對是否存在。
輸入格式:
n,m 接下來n-1條邊a,b,c描述a到b有一條長度為c的路徑
接下來m行每行詢問乙個k
輸出格式:
對於每個k每行輸出乙個答案,存在輸出「aye」,否則輸出」nay」(不包含引號)
點分治裸題。。。
一種優化的暴力,可以方便的求出樹上兩點間的距離
我們知道,樹的重心可以使樹的深度最小(最壞n/2,期望logn)
我們在點分治時就可以這麼來優化
每次找到樹的重心,然後遍歷子樹,dfs計算出每一條經過重心的路徑長度
然後刪掉重心,每個新形成的樹再跑一遍
直到無法遞迴為止
長度記下來,o(1)查詢即可
#include#include#include
#define rii register int i
#define rij register int j
using
namespace
std;
bool bj[10000005
];struct
ljbx[
20005
];int sd,lsl,cnt,head[10005],last[10005
],ans,n,m,k;
int cd[10005],ks[10005],js[10005],zg[10005],size[10005
];int judge[10005
];void dfs1(int wz,int fa,int
sd) dfs1(x[ltt].to,wz,sd+x[ltt].val);
ltt=x[ltt].next;
}return;}
int dfs(int wz,int
fa) ltt=x[ltt].next;
}if(size[wz]*2>=n&&!ans)
return0;
}void updata(int l,int
r) }
return;}
void solve(int
wz)
int ltt=head[zx];
while(ltt!=0
)
ltt=x[ltt].next;
}for(rii=1;i<=lsl;i++)
}for(rii=1;i<=cnt;i++)
zg[zx]=1
; ltt=head[wz];
while(ltt!=0
)
ltt=x[ltt].next;
}return;}
intmain()
x[i*2-1].to=kkk;
x[i*2-1].val=val;
if(last[ltt]!=0
)
last[ltt]=i*2-1
;
if(head[kkk]==0
)
x[i*2].to=ltt;
x[i*2].val=val;
if(last[kkk]!=0
)
last[kkk]=i*2
; bj[val]=1
; }
solve(1);
for(rii=1;i<=m;i++)
else
}}
點分治 模板 1
自己整理模板,僅作模板儲存使用 樹上點分治模板 1 該模板有一巨大bug 在統計路徑長度為單邊長度時,會出錯 include include include include using namespace std define inf 999999999 int n,m,len 0,size str...
點分治模板
luogu 3806 近些日子學了點分治,當然只是學了個模板。所謂點分治,使用於處理樹上路徑的一種分治手段。因為利用了重心的性質,時間複雜度可以保證呢。所謂演算法流程 選取當前子樹的重心 計算路徑總數,不管路徑是否過當前重心 後面會去重 計算起點和終點在同一顆子樹中的合法路徑 因為這條路徑不是簡單路...
點分治模板
這兩天跟著學了一手樹上點分治模板,然後有一些感悟,決定來寫一發部落格.首先,鑑於鄙人的經驗,如果想要較快速地學習乙個新演算法,肯定還是先看一道經典的例題比較好,所以我們先來一道例題.給你一棵tree,以及這棵樹上邊的距離.問有多少對點它們兩者間的距離小於等於k 輸入格式 n n 40000 接下來n...