COCI2020.11 T5

Posted KJGKMTZB

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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");
}

以上是关于COCI2020.11 T5的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ_2223_[Coci 2009]PATULJCI_主席树

COCI 20152016 1st round 题解(官方)

COCI2011:友好数对

[COCI2017-2018#6] Alkemija

[Luogu5181][COCI2009]GENIJALAC

题解 P6467 [COCI2008-2009#6] BUKA