2 条题解
-
0
给定一棵以 为根的树,初始每个点都没被点亮,每个时刻可以改变一个点的点亮状态,需要让每个点 都在某个时刻满足”有且仅有 的子树被点亮“,最终所有点都没被点亮。求至少经过多少时刻。
。
转化一下题意:记 为 子树大小。对于一条树边 ,在新图 上添加 之间权值为 的双向边;对于一个点 ,在 上添加 和新点 之间权值为 的边。则原问题等价于找到一个边的多重集,满足:
- 中的每个点度数都 且为偶数。
- 连通。
如果满足这两个条件,就可以构造出一组 出发的欧拉回路,其中 表示没有任何点点亮的状态, 表示仅 子树点亮的状态,则显然是充要条件。每条边只会被加入多重集 或 次,更多次显然是不优的。设计一个树形 dp 表示 子树是否满足以下条件的最小花费:
- 根节点是否与 连通。需要保证所有不与根节点连通的结点都与 连通。
- 根节点的度数是否是奇数。
转移先考虑第一维。有 。其实是 边的选择次数,所以 。
然后合并 连通块和儿子 子树,其中 代表 中 的权值:
- 选 次。。
- 选 次。$f_{u,i,j}+f_{v,i',1}+w\to f'_{u,i\operatorname{or} i',j\operatorname{xor} 1}$。
- 选 次。$f_{u,i,j}+f_{v,i',0}+2w\to f'_{u,i\operatorname{or} i',j}$。
wow,居然 了。
-
0
#include<bits/stdc++.h> using namespace std; typedef long long ll; constexpr int N=2e5+5,INF=1e9; int n,siz[N]; ll f[N][3]; vector<int> G[N]; void dfs(int x){ siz[x]=1; for(auto &y:G[x]) dfs(y), siz[x]+=siz[y]; f[x][0]=0,f[x][1]=siz[x],f[x][2]=siz[x]<<1; for(auto &y:G[x]){ int z=siz[x]-siz[y]; f[x][2]=min({f[x][2]+f[y][0]+(z<<1),f[x][0]+f[y][2]+(z<<1),f[x][1]+f[y][1]+z,f[x][2]+f[y][2]}); f[x][1]=min({f[x][1]+f[y][0]+(z<<1),f[x][0]+f[y][1]+z,f[x][1]+f[y][2]}); f[x][0]=min({f[x][0]+f[y][0]+(z<<1),f[x][0]+f[y][2]}); } } int main(){ scanf("%d",&n); for(int i=2,x;i<=n;i++){ scanf("%d",&x); G[x].emplace_back(i); } dfs(1); printf("%lld\n",f[1][2]); return 0; }
- 1
信息
- ID
- 7676
- 时间
- 2000ms
- 内存
- 256MiB
- 难度
- 8
- 标签
- 递交数
- 52
- 已通过
- 9
- 上传者