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 题解(官方)