首页 > 其他分享 >P7929 [COCI2021-2022#1] Logičari

P7929 [COCI2021-2022#1] Logičari

时间:2024-04-07 21:55:05浏览次数:27  
标签:rt COCI2021 rtc fa 2022 ans ari rt2c dp

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_back

typedef 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;
}

标签:rt,COCI2021,rtc,fa,2022,ans,ari,rt2c,dp
From: https://www.cnblogs.com/FireRaku/p/18120008

相关文章

  • 【更新】上市公司-ZF环保补贴、补助数据(2008-2022年)
    01、数据简介环保补贴,又称绿色补贴,是ZF在环保领域实施的一种特定补贴。它主要针对那些在经济主体意识上存在偏差或由于资金私有制而无法有效进行环保投资的企业。环保补贴的目的是解决环保问题,帮助企业改进环保设备和工艺,以减少对环境的损害。环保补助1=绿色补贴*100/营业总......
  • 【碳中和】上市公司碳信息披露数据-词频统计(1991-2022年)
    数据来源:上市公司年报时间跨度:1991-2022年数据范围:上市公司数据指标:低碳战略、宣传、方针、理念低碳方针低碳战略低碳宣传低碳理念低排放低碳计划低碳意识降碳计划降碳战略低碳发展零碳战略零碳低碳发展战略零低碳能源碳目标......
  • 【WEEK6】Learning Objectives and Summaries【MySQL】【English Version】
    LearningObjectives:TwoweekstofinishlearningMySQL-WeektwoLearningContent:Referencevideotutorials【狂神说Java】MySQL最新教程通俗易懂QuerydatabyDQLMySQLfunctionsMD5encryptionTransactionsLearningtimeandoutputs:Week6MON~WED,SUN......
  • CSP J 2022 第二轮 VP 划水记
    \(day0\)处于广州三区,CSP直接停掉。但是听说后续会有补测,但是无论如何,钩子应该是没有了。晚上最后复习了快速幂,线段树,树状数组,就去睡觉了。收到某人的祝福,挺好的(虽然远在我家隔壁一条街?)。\(day1\)中午\(12\)点开始考试,定个闹钟,到\(3:30\)。准时结束。开了第一题。题意:......
  • [蓝桥杯 2022 国 B] 齿轮(优化枚举)
        根据题目描述,如果采用dfs暴力做法枚举所有方案,肯定会超时,因此我们需要优化枚举,我们都知道在同一组共同转动的齿轮中,线速度相等,因此角速度的比值就是半径的反比,因此我们只需要找到对于每个齿轮作为起始齿轮,只需要找到其倍数半径是否存在即可,而倍数上限就是假设存在......
  • [蓝桥杯 2022 省 B] 李白打酒加强版(三维动态规划)
        通过题目描述,我们可以知道这道题目涉及到某种状态时候的方案数,因此我们可以用动态规划来解决问题,并且我们需要注意到酒的状态,因此我们可以用三维数组来存储状态,我们知道N,M最大不会超过100,并且如果酒超过了100斗,即使遇到100朵花也无法喝完,因此只需要定义大小都为1......
  • Arm架构下麒麟操作系统安装配置Mariadb数据库
    1、安装配置JDK(1)检查机器是否已安装JDK执行java-version命令查看机器是否安装JDK,一般麒麟操作系统默认安装openjdk1.8。  (2)安装指定版本JDK如果麒麟操作系统默认安装的openjdk1.8不符合需求的话,可以卸载机器安装的openjdk1.8并按需安装所需的openjdk版本,此步骤本文不......
  • [蓝桥杯 2022 国 A] 环境治理(二分 + 弗洛伊德)
        通过题目描述,我们得知如果枚举所有的天数,就不会通过所有的样例,因此我们可以通过二分来列举符合要求的天数,并且我们知道两个城市之间衡量的灰尘度标准就是灰尘度总和最小的那一段路径,也就是说我们需要寻找到权值和最低的那条路径,而我们知道每两个点之间都有路径......
  • 2022蓝桥杯大赛软件类国赛真题 卡牌
    importjava.util.Scanner;publicclassMain{staticfinalintN=200005;staticlongn,m;staticint[]a=newint[N];staticint[]b=newint[N];publicstaticvoidmain(String[]args){Scannersc=newScanner(System.in......
  • 【T5中的激活函数】GLU Variants Improve Transformer
    【mT5中的激活函数】GLUVariantsImproveTransformer论文信息阅读评价AbstractIntroductionGatedLinearUnits(GLU)andVariantsExperimentsonText-to-TextTransferTransformer(T5)Conclusion论文信息名称内容论文标题GLUVariantsImprov......