給定一棵樹,找一些路徑滿足,路徑上0,1數量相等,並在路徑上找到乙個點(休息站),改點到路徑兩端上0,1數量也相等,同一條路徑點不同,記為不同,詢問有多少條路徑滿足條件
點分治
對於乙個點
u 我們遍歷每棵子樹中的節點
v,求出di
s(u,
v),我們記錄這條路徑上有無節點
t 使得di
s(v,
t)=0
存在陣列裡
休息站一定在起點到根的路徑上或根到終點的路徑上
合併兩條路徑時選取只有一條有休息站的或者兩條都有的
const
maxn=200005;
var w:array[0..3*maxn,1..3]of longint;
size,maxx,vis,dis:array[0..maxn]of longint;
x:array[-maxn..maxn]of longint;
f,g:array[-maxn..maxn,0..1]of int64;
i,j,k:longint;
n,m,len,a,b,c,root,cnt,mx,mxdep:longint;
ans:int64;
function
max(a,b:longint):longint;
begin
if a>b then
exit(a) else
exit(b); end;
procedure
init
(a,b,c:longint);
begin
w[len,1]:=b; w[len,2]:=c; w[len,3]:=0;
if (w[a,3]=0) then w[a,3]:=len else w[w[a,1],3]:=len;
w[a,1]:=len; inc(len);
end;
procedure
getroot
(a,fa:longint);
var tt:longint;
begin
tt:=w[a,3]; size[a]:=1; maxx[a]:=0;
while (tt<>0) do
begin
if (w[tt,1]<>fa)and(vis[w[tt,1]]=0) then
begin
getroot(w[tt,1],a);
inc(size[a],size[w[tt,1]]);
maxx[a]:=max(maxx[a],size[w[tt,1]]);
end;
tt:=w[tt,3];
end;
maxx[a]:=max(maxx[a],cnt-size[a]);
if (root=0)or(maxx[a]then root:=a;
end;
procedure
getdep
(a,fa,b:longint);
var tt:longint;
begin
tt:=w[a,3]; mxdep:=max(mxdep,b);
if (x[dis[a]]=0) then g[dis[a],0]:=g[dis[a],0]+1
else g[dis[a],1]:=g[dis[a],1]+1;
inc(x[dis[a]]);
while (tt<>0) do
begin
if (w[tt,1]<>fa)and(vis[w[tt,1]]=0) then
begin
dis[w[tt,1]]:=dis[a]+w[tt,2];
getdep(w[tt,1],a,b+1);
end;
tt:=w[tt,3];
end;
dec(x[dis[a]]);
end;
procedure
treedc
(a:longint);
var tt,i:longint;
begin
tt:=w[a,3]; vis[a]:=1; mx:=0; f[0,0]:=1;
while (tt<>0) do
begin
if (vis[w[tt,1]]=0) then
begin
mxdep:=0;
dis[w[tt,1]]:=w[tt,2];
mxdep:=1; getdep(w[tt,1],0,1); mx:=max(mx,mxdep);
ans:=ans+g[0,0]*(f[0,0]-1);
for i:=-mxdep to mxdep do
ans:=ans+g[i,0]*f[-i,1]+g[i,1]*f[-i,0]+g[i,1]*f[-i,1];
for i:=-mxdep to mxdep do
begin
f[i,0]:=f[i,0]+g[i,0]; f[i,1]:=f[i,1]+g[i,1];
g[i,0]:=0; g[i,1]:=0;
end;
end;
tt:=w[tt,3];
end;
for i:=-mx to mx do
begin f[i,0]:=0; f[i,1]:=0; end;
tt:=w[a,3];
while (tt<>0) do
begin
if (vis[w[tt,1]]=0) then
begin
root:=0; cnt:=size[w[tt,1]]; getroot(w[tt,1],0);
treedc(root);
end;
tt:=w[tt,3];
end;
end;
begin
readln(n); len:=n+1;
for i:=1
to n-1
dobegin readln(a,b,c); if (c=0) then c:=-1; init(a,b,c); init(b,a,c); end;
root:=0; cnt:=n; getroot(1,0);
ans:=0; treedc(root);
writeln(ans);
end.
bzoj3697 採藥人的路徑
這是個思路題,對我這樣的zz 來說可能已經接近自己想出來的極限了。一看統計符合條件的路徑條數,肯定是點分治,而且肯定是靜態的。首先把邊權變成 1 和 1 那麼一條路徑陰陽平衡也就是說它的權值和等於 0 根據點分治的過程,可知重心和路徑是一對多的關係,而且一條路徑只會對應乙個重心,就是說每條路徑都只會...
bzoj3697 採藥人的路徑
description 採藥人的藥田是乙個樹狀結構,每條路徑上都種植著同種藥材。採藥人以自己對藥材獨到的見解,對每種藥材進行了分類。大致分為兩類,一種是陰性的,一種是陽性的。採藥人每天都要進行採藥活動。他選擇的路徑是很有講究的,他認為陰陽平衡是很重要的,所以他走的一定是兩種藥材數目相等的路徑。採藥工...
bzoj3697 採藥人的路徑 點分治
一道拖了很久的點分治,現在把他搞定了。來自出題人hta的題解 本題可以考慮樹的點分治。問題就變成求過根滿足條件的路徑數。路徑上的休息站一定是在起點到根的路徑上,或者根到終點的路徑上。如何判斷一條從根出發的路徑是否包含休息站?只要在dfs中記錄下這條路徑的和x,同時用個標誌陣列判斷這條路徑是否存在字首...