BZOJ3697 採藥人的路徑

2021-07-10 08:09:07 字數 3140 閱讀 5499

給定一棵樹,找一些路徑滿足,路徑上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,同時用個標誌陣列判斷這條路徑是否存在字首...