专栏文章

题解:P8127 [BalticOI 2021] The Xana coup (Day2)

P8127题解参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@minbqob8
此快照首次捕获于
2025/12/01 23:48
3 个月前
此快照最后确认于
2025/12/01 23:48
3 个月前
查看原文
由于题目给的是一棵树,很明显要用树形 DP。
根据 DP 的步骤。我们先定义状态。
可以发现树上的节点 ii,可能最后结果为 0011,可能操作了也可能没操作,所以有 2×2=42\times2=4 种情况。
定义 dpdp 数组,表示以 ii 为根的子树除了点 ii 都为 00 的最小操作数,又有上述的 44 种情况:
  • dpi,0,0dp_{i,0,0},表示节点 ii,最后结果为 00,并且没在 ii 进行过操作。
  • dpi,0,1dp_{i,0,1},表示节点 ii,最后结果为 00,并且在 ii 进行过操作。
  • dpi,1,0dp_{i,1,0},表示节点 ii,最后结果为 11,并且没在 ii 进行过操作。
  • dpi,1,1dp_{i,1,1},表示节点 ii,最后结果为 11,并且在 ii 进行过操作。
然后我们考虑初始化:
设当点 ii 初始状态为 aia_i。(\oplus 为异或)。
  • dpi,ai,0=0dp_{i,a_i,0} = 0。表示点 ii 不操作,所以点 ii 没有变化。
  • dpi,ai1,1=1dp_{i,a_i\oplus1,1} = 1。表示点 ii 操作,所以点 ii 变化了。
  • dpi,0,1=dp_{i,0,1} = \infty。此操作不可行。
  • dpi,1,0=dp_{i,1,0} = \infty。此操作不可行。
之后考虑转移。
jjii 的子节点。
可以分为两种情况:
  • jj 操作过,则点 ii 状态被改变。
    • dpi,0,0=dpi,1,0+dpj,0,1dp_{i,0,0}=dp_{i,1,0}+dp_{j,0,1}
    • dpi,1,0=dpi,0,0+dpj,0,1dp_{i,1,0}=dp_{i,0,0}+dp_{j,0,1}
    • dpi,0,1=dpi,1,1+dpj,1,1dp_{i,0,1}=dp_{i,1,1}+dp_{j,1,1}
    • dpi,1,1=dpi,0,1+dpj,1,1dp_{i,1,1}=dp_{i,0,1}+dp_{j,1,1}
  • jj 没操作过,则点 ii 状态没被改变。
    • dpi,0,0=dpi,0,0+dpj,0,0dp_{i,0,0}=dp_{i,0,0}+dp_{j,0,0}
    • dpi,1,0=dpi,1,0+dpj,0,0dp_{i,1,0}=dp_{i,1,0}+dp_{j,0,0}
    • dpi,0,1=dpi,0,1+dpj,1,0dp_{i,0,1}=dp_{i,0,1}+dp_{j,1,0}
    • dpi,1,1=dpi,1,1+dpj,1,0dp_{i,1,1}=dp_{i,1,1}+dp_{j,1,0}
这两种情况取较小值。
由于转移中需要要用到本身,为了防止出现一种状态使用已转移的状态来转移,所以在每次转移前先用 44 个变量把每种状态记录下来,用记录下来的值转移。
最后是输出答案,设我们已 rootroot 为树根开始计算,则答案为 min(dproot,0,1,dproot,0,0)\min(dp_{root,0,1},dp_{root,0,0})
codeCPP
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int maxn=2e5+5,inf=1e15;
int a[maxn],b[maxn],c[maxn][2][2],n,m,d[maxn];
vector<int>aa[maxn];
void dfs(int x,int fa)
{
	c[x][a[x]][0]=0;
	c[x][a[x]^1][1]=1;
	c[x][a[x]][1]=c[x][a[x]^1][0]=inf;
	for(int i=0;i<aa[x].size();i++)
	{
		int to=aa[x][i];
		if(to==fa)continue;
		dfs(to,x);
		int c00=c[x][0][0],c01=c[x][0][1],c10=c[x][1][0],c11=c[x][1][1];
		c[x][0][0]=min(c00+c[to][0][0],c10+c[to][0][1]);
		c[x][1][0]=min(c00+c[to][0][1],c10+c[to][0][0]);
		c[x][0][1]=min(c01+c[to][1][0],c11+c[to][1][1]);
		c[x][1][1]=min(c11+c[to][1][0],c01+c[to][1][1]);
	}
}
signed main()
{
	ios::sync_with_stdio(0);
	cin.tie(0),cout.tie(0);
	cin>>n;
	for(int i=1;i<n;i++)
	{
		int x,y;
		cin>>x>>y;
		aa[x].push_back(y);
		aa[y].push_back(x);
	}
	for(int i=1;i<=n;i++)cin>>a[i];
	dfs(1,0);
	int z=min(c[1][0][0],c[1][0][1]);
	if(z<inf)cout<<z;
	else cout<<"impossible";
    return 0;
}

评论

0 条评论,欢迎与作者交流。

正在加载评论...