[CSP-S模拟测试]:卡常题/b(基环树+DP)

题目描述

$ρ$有一个二分连通无向图,$X$方点、$Y$方点均为$n$个(编号为$1\sim n$)。
这个二分图比较特殊,每一个$Y$方点的度为$2$,一条黑色边,一条白色边。
所有黑色边权值均为$a$,所有白色边权值均为$b$。
选择一个$X$方点,代价为连接的所有边的权值之和。
激活一个$Y$方点,需要选择至少一个与之相邻的$X$方点。
现在,$ρ$想激活每个$Y$方点,他想知道最小的总代价。
不过$ρ$很善良,他给你开了$O2$优化。
这样你就不会被卡常了。
当然,除非你真的连读入优化都不想写,或者常数真的丑死。


输入格式

第一行:三个正整数$n$、$a$、$b$。
接下来$n$行:每行两个正整数,第$i$行表示第$i-1$个$Y$方点的黑色边连接的$X$方点,白色边连接的$X$方点。


输出格式

第一行:一个整数,代表最小的总代价。


样例

样例输入:

4 2 3
1 2
3 1
1 4
2 3

样例输出:

12


数据范围与提示

$20\%$的数据:$n\leqslant 20$。
$40\%$的数据:$n\leqslant {10}^3$。
另外$10\%$的数据:$a=b=1$。
另外$20\%$的数据:保证每个$X$方点连接的边颜色相同。
另外$10\%$的数据:保证原图是一个大小为$2\times n$的环。
$100\%$的数据:$n\leqslant {10}^6,a,b\leqslant 100$,保证无重边。


题解

发现这张图其实就是一个基环树,所以我们可以做基环树$DP$。

首先,找到这个环,然后删掉这条边,这样就变成了一棵树了,向两个方向进行$DP$,取较小的即可。

时间复杂度:$\Theta(n)$。

期望得分:$100$分。

实际得分:$100$分。


代码时刻

#include<bits/stdc++.h>
using namespace std;
struct rec{int nxt,to;}e[2000001];
struct node{int i,l,r;}root;
int head[1000001],cnt=1;
int n,a,b;
int sam[1000001];
int dp[2][1000001][2];
bool vis[1000001];
void add(int x,int y)
{
	e[++cnt].nxt=head[x];
	e[cnt].to=y;
	head[x]=cnt;
}
void pre_dfs(int x,int fa)
{
	vis[x]=1;
	for(int i=head[x];i;i=e[i].nxt)
	{
		if(e[i].to==fa)continue;
		if(vis[e[i].to]){root=(node){i,x,e[i].to};return;}
		pre_dfs(e[i].to,x);
	}
}
void DP0(int x,int fa)
{
	int sum=0;
	dp[0][x][0]=0;
	dp[0][x][1]=sam[x];
	for(int i=head[x];i;i=e[i].nxt)
	{
		if(i==root.i||(i^1)==root.i||e[i].to==fa)continue;
		DP0(e[i].to,x);
		sum+=min(dp[0][e[i].to][0],dp[0][e[i].to][1]);
		dp[0][x][0]+=dp[0][e[i].to][1];
	}
	dp[0][x][1]+=sum;
}
void DP1(int x,int fa)
{
	int sum=0;
	dp[1][x][0]=0;
	dp[1][x][1]=sam[x];
	for(int i=head[x];i;i=e[i].nxt)
	{
		if(i==root.i||(i^1)==root.i||e[i].to==fa)continue;
		DP1(e[i].to,x);
		sum+=min(dp[1][e[i].to][0],dp[1][e[i].to][1]);
		dp[1][x][0]+=dp[1][e[i].to][1];
	}
	dp[1][x][1]+=sum;
}
int main()
{
	scanf("%d%d%d",&n,&a,&b);
	for(int i=1;i<=n;i++)
	{
		int x,y;
		scanf("%d%d",&x,&y);
		sam[x]+=a;sam[y]+=b;
		add(x,y);add(y,x);
	}
	pre_dfs(1,0);
	DP0(root.l,0);
	DP1(root.r,0);
	cout<<min(dp[0][root.l][1],dp[1][root.r][1])<<endl;
	return 0;
}


rp++

原文地址:https://www.cnblogs.com/wzc521/p/11498628.html

时间: 2024-10-28 15:19:43

[CSP-S模拟测试]:卡常题/b(基环树+DP)的相关文章

[CSP-S模拟测试]:小L的数(数位DP+模拟)

题目传送门(内部题132) 输入格式 第一行一个整数$t$. 接下来$t$行每行一个整数$n$. 输出格式 $t$行,每行一个整数表示答案. 样例 样例输入: 418182312326910521093203 样例输出: 1233 数据范围与提示 对于前$5\%$的测试数据,满足答案小于等于$1$. 对于前$20\%$的测试数据,满足答案小于等于$2$. 对于前$40\%$的测试数据,满足$n\leqslant 300,000$. 对于前$60\%$的测试数据,满足答案小于等于$3$,$n\le

[CSP-S模拟测试]:联(小清新线段树)

题目描述 由于出题人懒所以没有背景.一个无限长的$01$序列,初始全为$0$,每次选择一个区间$[l,r]$进行操作,有三种操作:$\bullet 1\ l\ r$将$[l,r]$中所有元素变成$1$.$\bullet 2\ l\ r$将$[l,r]$中所有元素变成$0$.$\bullet 3\ l\ r$将$[l,r]$中所有元素异或上$1$.每次操作后询问最左边的$0$在哪个位置. 输入格式 第一行一个数$m$,表示序列长度和操作数量.接下来$m$行,每行三个数$ty\ l\ r$,描述一次

2019年杭电多校第三场 1011题Squrirrel(HDU6613+树DP)

题目链接 传送门 题意 给你一棵无根树,要你寻找一个根节点使得在将一条边权变为\(0\)后,离树根最远的点到根节点的距离最小. 思路 本题和求树的直径很像,不过要记得的东西有点多,且状态也很多. \(fi[u][0]\)表示在\(u\)这个结点不删边沿着子树方向能到达的最远距离,\(se[u][0]\)为第二远,\(th[u][0]\)为第三远,\(fa[u][0]\)表示沿着父亲方向能到达的最远距离,第二维为\(1\)表示删一条边能到达的距离. 不删边的转移和求树的直径转移方程基本上是一样的,

Codeforces 988D Points and Powers of Two 【性质】【卡常】

这道题关键在于想到两个性质,想到就好做了.这还是我做过的第一道卡常题 1.满足题目中条件的子集,其中元素个数不能大于3 2.如果最大子集为3的话,那一定是x-2^i,  k, x+2^i的形式,我们枚举x就好了,然后i的次数是log10^9:如果最大子集是2,那就是x,x+2^i的形式,同样枚举x:如果最大子集是1,输出a[1]就行 整体复杂度是O(n*logn*log10^9) 1 #include<iostream> 2 #include<set> 3 using namesp

[CSP-S模拟测试]:Median(暴力+模拟)

题目描述 定义两个数列: $$S=\{S(1),S(2),...,S(n)\}\text{和}S_2\{S_2(1),S_2(2),...,S_2(n)\}$$ $$S(k)=(p_k\times k)\mod w,where\ p_k\ is\ the\ kth\ prime\ number$$ $$S_2(k)=S(k)+S(\left\lfloor\frac{k}{10}\right\rfloor+1)$$ 令$M(i,j)$表示$S_2(i)$到$S_2(j)$的中位数(个数为奇数就是中

[考试反思]1010csp-s模拟测试65:突袭

博客园挂了,不让粘图. 写的朴素一点. #1:100+100+25=225 #2:100+70+35=205 #2:100+60+45=205(我) 回到第一机房还算不错的第一仗. 考完之后我以为我AK了然而T2被卡常打成暴力,T3贪心伪证了(虽说是全场最高分) 全程在思考.很好啊. 继续保持. 注意常数,在卡常题上要花些时间优化打法卡常. T1:Simple 做法比较傻逼. 互质下才好做,所以把nm都干掉gcd,把这样贡献的答案先算上. 我们考虑列出一个表,每n个一行(n<=m). 这样如果某

2016年上半年软考真题在线模拟测试,提前知晓你的成绩

2016年上半年软考于5月21日结束了,考试完想知道结果的急切心理,几乎每个经历过上学时代的人都能深刻体验到.如果你想知道你考的怎么样,如果你想要提前知道你的成绩,如果你想知道你哪个地方出错了,如果你想知道你哪个地方知识掌握的不够想要更深入的去理解,那就来希赛软考学院吧!希赛软考学院提供2016年上半年软考真题在线模拟测试,有标准的参考答案,有专业老师的解析视频,让你提前知晓你的成绩,让你再次巩固学习. 希赛授课专家介绍 张友生,计算机应用技术博士,软考培训教程系列丛书主编,考试指定教材<系统分

2018冬令营模拟测试赛(十九)

2018冬令营模拟测试赛(十九) [Problem A]小Y 试题描述 输入 见"试题描述" 输出 见"试题描述" 输入示例 见"试题描述" 输出示例 见"试题描述" 数据规模及约定 见"试题描述" 题解 目前未知. 这题目前就能做到 \(O(n \sqrt{M} \log n)\),其中 \(M\) 是逆序对数,然而会被卡 \(T\):当然这题暴力可以拿到和左边那个算法一样的分数,只要暴力加一个剪枝:当左

论OI中各种玄学卡常

当你在写程序的时候一般出现过这种无比悲剧的情况: 你讨厌卡常?下面有二则小故事: 作为一个经常出题的人,其实很多时候出题时的画风是这样的:"我有一个绝妙的\(O(nlog^2n)\)的算法,我来出道题吧""咦怎么只能跑 \(5w\) 啊,好咸鱼啊,我要让它能跑 \(10w\),嗯现在 \(10w\) 只要 \(0.3s\) 了,要不努把力跑个 \(20w\) 吧"然后就没有然后了.. 开O2之后FFT会比不开快几倍? 不开\(O2\):\(NTT\)比\(FFT\)