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");
}
标签:xor,min,int,rep,T5,起始,yny,COCI2020.11 来源: https://www.cnblogs.com/A-Dance-of-Fire-and-Ice/p/14906404.html