COCI2020.11 T5

状态很显然,设\(f[x][i][j]\)表示在以\(x\)为根的子树内有\(i\)个起始点,当除了点\(x\)的其它点都被点亮且点\(x\)上的灯的状态为\(j\)时路径长度的\(min\)

接下来考虑转移(本篇参考了Tommy0103的博客,算是那篇博客的一篇补充)

若当前\(x\)内没有一个起始点,则其子树内也没有起始点,转移也非常显然,就是看下如何同时满足自己的状态的同时满足所有儿子为1

\(f[x][0][j]=min(f[x][0][j]+f[v][0][1]+4,f[x][0][j \ xor\ 1]+f[v][0][0]+2)\)

若当前\(x\)内有一个起始点,情况变得有点麻烦了起来,但也就是个分类讨论看看\(x\)是不是起始点

\(f[x][1][j]=min(min(f[x][0][j \ xor \ 1]+f[v][1][1]+1,f[x][0][j]+f[v][1][0]+3),min(f[x][1][j \ xor \ 1]+f[v][0][0]+2,f[x][1][j]+f[v][0][1]+4))\)

前半截是要从\(v\)开始走,后半截是要从\(x\)开始走

上两种情况的重点在于因为\(x\)内没有包含两个起始点,所以无论怎么走一定会回到\(x\),下面来看最复杂的情况

考虑\(x\)和当前要转移的子树都有\(1\)个起始点

因为起点重点反过来路径一样,所以考虑子树中的那个为终点,则易有转移

\(min(f[x][1][j^1]+f[v][1][0]+2,f[x][1][j]+f[v][1][1])\)

因为它没必要走回去所以不必\(+4\),这里非常重要

剩下的就一样了,两种情况转移分别为

\(min(f[v][0][0]+f[x][2][j \ xor \ 1]+2,f[v][0][1]+f[x][2][j]+4)\)

\(min(f[v][2][0]+g[0][j \ xor \ 1]+2,f[v][2][1]+g[0][j]+4)\)

最后再把\(x\)做为起始点的情况转移一下就行了

code

#include <bits/stdc++.h>
#define rep(a,b,c) for(int a=(b);a<=(c);a++)
#define per(a,b,c) for(int a=(b);a>=(c);a--)
#define repe(a) for(int yny=head[a],v;yny&&(v=e[yny].v);yny=e[yny].u)
using namespace std;
const int N=5e5+5;
struct Edge {
	int u,v;
}e[N*2];
int head[N],ecnt;
inline void adde(int u,int v) { e[++ecnt].v=v;e[ecnt].u=head[u];head[u]=ecnt; }
inline void add(int u,int v) { adde(u,v); adde(v,u); }
inline int min(int a,int b,int c) { return min(a,min(b,c)); }
int f[N][3][2],sz[N];
char s[N];
int n,a,b;
inline void dfs(int x,int fa) {
	int chk=(s[x]=='1');
	sz[x]=(chk^1);
	rep(i,0,2) rep(j,0,1) f[x][i][j]=(4*n+1);
	f[x][0][chk]=0; f[x][1][chk^1]=1;
	int g[3][2];
	repe(x) if(v!=fa) {
		dfs(v,x);
		sz[x]+=sz[v];
		if(!sz[v]) continue;
		rep(i,0,2) rep(j,0,1) g[i][j]=f[x][i][j];
		rep(j,0,1) {
			f[x][0][j]=min(f[v][0][0]+g[0][j^1]+2,f[v][0][1]+g[0][j]+4);
			f[x][1][j]=min(min(f[v][0][0]+g[1][j^1]+2,f[v][0][1]+g[1][j]+4),min(f[v][1][1]+g[0][j^1]+1,f[v][1][0]+g[0][j]+3));
			f[x][2][j]=min(min(f[v][1][0]+g[1][j^1]+2,f[v][1][1]+g[1][j]),min(f[v][0][0]+g[2][j^1]+2,f[v][0][1]+g[2][j]+4),min(f[v][2][0]+g[0][j^1]+2,f[v][2][1]+g[0][j]+4));
		}
	}
	rep(i,0,2) rep(j,0,1) g[i][j]=f[x][i][j];
	rep(j,0,1) {
		f[x][1][j]=min(f[x][1][j],g[0][j^1]+1);
		f[x][2][j]=min(f[x][2][j],g[1][j]);
	}
}
int main() {
	scanf("%d",&n);
	scanf("%s",s+1);
	rep(i,2,n) scanf("%d %d",&a,&b),add(a,b);
	rep(i,1,n) if(s[i]=='0') {
		dfs(i,0);
		printf("%d\n",f[i][2][1]);
		return 0;
	}
	puts("0");
}
上一篇:人生苦短,我学python day15 时间、hash和json


下一篇:Physical Education Lessons [CodeForces - 915E ]T5 D3