【NOIP2018提高组D2T3】保卫王国

抱歉,本人蒟蒻没能做出,不过可给标程,orz大佬
在这里插入图片描述

const maxn=100000;inf=trunc(1e+12)-1;
var
f : array[0..maxn,0..17,0..1,0..1]of int64;
up,dw : array[0..maxn,0..1]of int64;
fa : array[0..maxn,0..17]of longint;
go,nxt : array[1..maxn*2]of longint;
dep,head,p : array[0..maxn]of longint;
i,j,n,m,x,y,a,b,tail,f1,w : longint;
function min(a,b:int64):int64;
begin	
	if a<b then exit(a);
	exit(b);
end;
procedure add(u,v:longint);
begin
	inc(tail);go[tail]:=v;
	nxt[tail]:=head[u];head[u]:=tail;
end;
procedure dfs1(x:longint);
var i:longint;
	begin
		dw[x,1]:=p[x];dw[x,0]:=0;
		dep[x]:=dep[fa[x,0]]+1;i:=head[x];
		while i<>0 do begin
			if go[i]<>fa[x,0] then begin
				fa[go[i],0]:=x;dfs1(go[i]);
				dw[x,0]:=dw[x,0]+dw[go[i],1];
				dw[x,1]:=dw[x,1]+min(dw[go[i],1],dw[go[i],0]);
			end;i:=nxt[i];
		end;
	end;
procedure dfs2(x:longint);
var i:longint;
	begin
		i:=head[x];
		while i<>0 do begin
			if go[i]<>fa[x,0] then begin
				up[go[i],0]:=up[x,1]+dw[x,1]-min(dw[go[i],1],dw[go[i],0]);
				up[go[i],1]:=min(up[go[i],0],up[x,0]+dw[x,0]-dw[go[i],1]);
				dfs2(go[i]);
			end;i:=nxt[i];
		end;
	end;
function lca(x,a,y,b:longint):int64;
var
tx,dx,ty,dy : array[0..1]of int64;//t=top
ans1,ans2 : int64;
i,j,k : longint;
	begin
		if dep[x]<dep[y] then begin
			i:=x;x:=y;y:=i;i:=a;a:=b;b:=i;
		end;
		tx[a]:=dw[x,a];tx[1-a]:=inf;
		ty[b]:=dw[y,b];ty[1-b]:=inf;
		i:=17;
		while dep[x]>dep[y] do begin
			while dep[fa[x,i]]<dep[y] do dec(i);
			dx[0]:=inf;dx[1]:=inf;
			for k := 0 to 1 do 
			for j := 0 to 1 do 
			dx[j]:=min(dx[j],tx[k]+f[x,i,k,j]);
			tx:=dx;
			x:=fa[x,i];
		end;
		if x=y then exit(tx[b]+up[y,b]);
		i:=17;
		while fa[x,0]<>fa[y,0] do begin
			while fa[x,i]=fa[y,i] do dec(i);
			dx[0]:=inf;dx[1]:=inf;dy:=dx;
			for k := 0 to 1 do 
			for j := 0 to 1 do begin
				dx[j]:=min(dx[j],tx[k]+f[x,i,k,j]);
				dy[j]:=min(dy[j],ty[k]+f[y,i,k,j]);
			end;
			tx:=dx;ty:=dy;
			x:=fa[x,i];y:=fa[y,i];
		end;
//		writeln(x,' ',y,' ',tx[0],' ',tx[1],' ',ty[0],' ',ty[1],' jump!!');
		
		k:=fa[x,0];
		ans1:=dw[k,1]-min(dw[x,1],dw[x,0])-min(dw[y,1],dw[y,0])
		+min(tx[0],tx[1])+min(ty[0],ty[1])+up[k,1];
		ans2:=dw[k,0]-dw[x,1]-dw[y,1]+tx[1]+ty[1]+up[k,0];
		exit(min(ans1,ans2));
	end;
begin
assign(input,'defense.in');reset(input);
assign(output,'defense.out');rewrite(output);
	readln(n,m);
	for i := 1 to n do read(p[i]);
	for i := 1 to n-1 do begin
		readln(x,y);
		add(x,y);add(y,x);
	end;
	dfs1(1);    dfs2(1);
	for i := 1 to n do begin
		f[i,0,0,0]:=inf;
		f[i,0,0,1]:=dw[fa[i,0],1]-min(dw[i,1],dw[i,0]);
		f[i,0,1,0]:=dw[fa[i,0],0]-dw[i,1];
		f[i,0,1,1]:=f[i,0,0,1];
	end;
	for j := 1 to 17 do 
	for i := 1 to n do begin
		f1:=fa[i,j-1];
		fa[i,j]:=fa[f1,j-1];
		for x := 0 to 1 do 
		for y := 0 to 1 do 
		begin
			f[i,j,x,y]:=inf;
			for w := 0 to 1 do 
			f[i,j,x,y]:=min(f[i,j,x,y],f[i,j-1,x,w]+f[f1,j-1,w,y]);
//			writeln(i,' ',fa[i,j],' ',x,' ',y,' : ',f[i,j,x,y]);
		end;
	end;
	
	for i := 1 to m do begin
		readln(x,a,y,b);
		if (a+b=0)and((fa[y,0]=x)or(fa[x,0]=y)) then begin writeln(-1);continue;end;
		writeln(lca(x,a,y,b));
	end;
close(input);close(output);
end.

猜你喜欢

转载自blog.csdn.net/Larry1118/article/details/85015574