P7929 [COCI2021-2022#1] Logičari

news/发布时间2024/5/6 2:35:04

P7929 [COCI2021-2022#1] Logičari

基环树 dp

基环树 dp 类似树形 dp,大致思路是把环断开,分类讨论之后树形 dp

如果在树上做这题,设 \(f_{u,0/1,0/1}\) 表示考虑到 \(u\) 结点,\(u\) 结点否/是染色、\(fa_u\) 否/是染色的最小染色点数。转移有:

\(fa_u\) 被染色了,\(f_{u,0/1,1}=\sum f_{v,1,0/1}\)

\(fa_u\) 没有被染色,这时候考虑 \(val=\sum f_{v,1,0/1}\),枚举一个 \(v\) 点染色,\(f_{u,0/1,0}=\min(val-f_{v,0,0/1}+f_{v,1,0/1})\)

在本题里,我们只需要额外讨论多出的一条边对点的染色情况的影响即可,这里需要多一些特判还需要把 dp 跑四次,分别固定了不同的染色情况。由于此题的状态较复杂,考虑用记忆化搜索跑 dp,更简洁。

建树操作用并查集维护。

复杂度 \(O(n\log n)\),由于并查集。事实上,找环的操作可以 \(O(n)\),只需要遍历时找到第一条非树边即可。

#include <bits/stdc++.h>
#define pii std::pair<int, int>
#define fi first
#define se second
#define pb push_backtypedef long long i64;
const i64 iinf = 0x3f3f3f3f, linf = 0x3f3f3f3f3f3f3f3f;
const int N = 1e5 + 10;
int n, rt, rt2, rtc, rt2c;
i64 ans = iinf;
int fa[N], anc[N];
int find(int x) {if(x != fa[x]) fa[x] = find(fa[x]);return fa[x];
}
struct node {int to, nxt;
} e[N << 1];
int h[N], cnt;
void add(int u, int v) {e[++cnt].to = v;e[cnt].nxt = h[u];h[u] = cnt;
}
i64 f[N][2][2];
void dfs(int u, int fa) {anc[u] = fa;for(int i = h[u]; i; i = e[i].nxt) {int v = e[i].to;if(v == fa) continue;dfs(v, u);}
}
int dp(int u, int col, int fac) {if(f[u][col][fac] != -1) return f[u][col][fac];bool vis = 1;if(u == rt2 && col != rt2c) vis = 0; if(u == rt2 && fac && rtc) vis = 0; if(!vis) return f[u][col][fac] = iinf;i64 ret = iinf, sum = col;bool fg = 0; //记录此时儿子是否可以被染色if(fac) fg = 1;if(u == rt2 && rtc) fg = 1; //特判for(int i = h[u]; i; i = e[i].nxt) {int v = e[i].to;if(v == anc[u]) continue;sum += dp(v, 0, col);}if(fg) {ret = std::min(ret, sum);} else {for(int i = h[u]; i; i = e[i].nxt) {int v = e[i].to;if(v == anc[u]) continue;ret = std::min(ret, sum - dp(v, 0, col) + dp(v, 1, col));}}return f[u][col][fac] = ret;
}
void Solve() {std::cin >> n;for(int i = 1; i <= n; i++) fa[i] = i;for(int i = 1; i <= n; i++) {int u, v;std::cin >> u >> v;int fu = find(u), fv = find(v);if(fu == fv) rt = u, rt2 = v;else {fa[fu] = fv;add(u, v), add(v, u);}}dfs(rt, 0);memset(f, -1, sizeof(f)), rtc = 0, rt2c = 0;dp(rt, rtc, rt2c);ans = std::min(ans, f[rt][rtc][rt2c]);memset(f, -1, sizeof(f)), rtc = 0, rt2c = 1;dp(rt, rtc, rt2c);ans = std::min(ans, f[rt][rtc][rt2c]);memset(f, -1, sizeof(f)), rtc = 1, rt2c = 0;dp(rt, rtc, rt2c);ans = std::min(ans, f[rt][rtc][rt2c]);memset(f, -1, sizeof(f)), rtc = 1, rt2c = 1;dp(rt, rtc, rt2c);ans = std::min(ans, f[rt][rtc][rt2c]);if(ans == iinf) std::cout << "-1\n";else std::cout << ans << "\n";
}
int main() {std::ios::sync_with_stdio(false);std::cin.tie(nullptr);Solve();return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ulsteruni.cn/article/10286158.html

如若内容造成侵权/违法违规/事实不符,请联系编程大学网进行投诉反馈email:xxxxxxxx@qq.com,一经查实,立即删除!

相关文章

Java登陆第四十天——Router路由守卫练习

需求 未登录无法访问除login页面 练习 1.使用vite创建项目,导入依赖 npm create vite 选择vue+js npm i 导入基本依赖 npm vue-router 导入路由依赖2. 创建组件,login.vue、home.vue、list.vue 仅展示home.vue组件,其他都一样。 <script setup></script><tem…

Nginx 解析漏洞复现

该漏洞与php和nginx版本无关,是配置错误导致的问题 漏洞描述 通常在nginx.conf的配置文件或者include包含的其他配置文件下有以下信息 location ~ \.php$ {fastcgi_index index.php;include fastcgi_params;fastcgi_param REDIRECT_STATUS 200;fastcgi_param SCRIPT_FILE…

阿里云服务器+NAS

什么是ECS ECS:即Elastic Compute Service 弹性计算(Elastic Computing)是一种云计算服务模型,它旨在提供灵活、自动且可伸缩的计算资源。弹性计算的关键特性包括:弹性伸缩: 用户可以根据实际需求自动调整计算资源的规模,实现按需分配和释放。这意味着在峰值时段增加资源…

uniapp 连接华为手机 usb调试 选择 音频来源

uniapp 连接华为手机 usb调试 选择 音频来源--------------------------------------------- 生活的意义就是你自己知道你要做什么,明确目标。没有目标,后面都是瞎扯! https://pengchenggang.gitee.io/navigator/ SMART原则:目标必须是具体的(Specific) 目标必须是可以衡…

Flask 脚本

一 集成Python Shell 作用: 一些任务更适合在shell中完成, 如后台添加超管需求、迁移数据库、定时任务等1.1 安装库 pip install flask-script 1.2 简单实现 项目目录 server.pyfrom flask import Flaskapp = Flask(__name__)@app.route(/) def hello_world():return Hello Wor…