专栏文章
题解: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 的步骤。我们先定义状态。
可以发现树上的节点 ,可能最后结果为 或 ,可能操作了也可能没操作,所以有 种情况。
定义 数组,表示以 为根的子树除了点 都为 的最小操作数,又有上述的 种情况:
- ,表示节点 ,最后结果为 ,并且没在 进行过操作。
- ,表示节点 ,最后结果为 ,并且在 进行过操作。
- ,表示节点 ,最后结果为 ,并且没在 进行过操作。
- ,表示节点 ,最后结果为 ,并且在 进行过操作。
然后我们考虑初始化:
设当点 初始状态为 。( 为异或)。
- 。表示点 不操作,所以点 没有变化。
- 。表示点 操作,所以点 变化了。
- 。此操作不可行。
- 。此操作不可行。
之后考虑转移。
设 为 的子节点。
设 为 的子节点。
可以分为两种情况:
- 操作过,则点 状态被改变。
- 。
- 。
- 。
- 。
- 没操作过,则点 状态没被改变。
- 。
- 。
- 。
- 。
这两种情况取较小值。
由于转移中需要要用到本身,为了防止出现一种状态使用已转移的状态来转移,所以在每次转移前先用 个变量把每种状态记录下来,用记录下来的值转移。
最后是输出答案,设我们已 为树根开始计算,则答案为 。
code
CPP#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 条评论,欢迎与作者交流。
正在加载评论...