首页 > 其他分享 >【做题记录】2025提高刷题-dp

【做题记录】2025提高刷题-dp

时间:2025-01-23 11:10:04浏览次数:1  
标签:fa int void vis 2025 maxn mem dp 刷题

A. Min-Fund Prison (Medium)
考虑一个边双连通分量一定不可能分为合法的两部分,于是进行缩点。缩完后显然是一个森林。
设 \(dp_{i,j,0/1}\) 表示第一堆有 \(i\) 个点,第二堆有 \(j\) 个点,两堆点有没有用一条边连起来的最小花费。对于每棵树,考虑将它加入第一堆/加入第二堆/一部分加入第一堆另一部分加入第二堆。时间复杂度 \(O(n^3)\)。

Code
#include<bits/stdc++.h>
#define int long long
#define il inline
#define pb push_back
#define mem(a,b) memset(a,b,sizeof a)
using namespace std;
namespace asbt{
namespace cplx{bool begin;}
namespace IO{
	const int bufsz=1<<20;
	char ibuf[bufsz],*p1=ibuf,*p2=ibuf;
	#define getchar() (p1==p2&&(p2=(p1=ibuf)+fread(ibuf,1,bufsz,stdin),p1==p2)?EOF:*p1++)
	template<typename T=int>il T read(){
		char ch=getchar();
		while(ch<'0'||ch>'9'){
			ch=getchar();
		}
		T x=0;
		while(ch>='0'&&ch<='9'){
			x=(x<<1)+(x<<3)+(ch^48);
			ch=getchar();
		}
		return x;
	}
	#undef getchar
	char obuf[bufsz],*p3=obuf,s[50];
	il int flush(){
		fwrite(obuf,1,p3-obuf,stdout);
		p3=obuf;
		return 0;
	}
	#define putchar(ch) (p3==obuf+bufsz&&flush(),*p3++=(ch))
	template<typename T>il void write(T x,bool typ=1){
		if(x<0){
			putchar('-');
			x=-x;
		}
		int top=0;
		do{
			s[++top]=x%10|48;
			x/=10;
		}while(x);
		while(top){
			putchar(s[top--]);
		}
		putchar(typ?'\n':' ');
	}
	#undef putchar
}
using IO::read;
using IO::write;
const int maxn=305,inf=0x3f3f3f3f3f3f3f3f;
int T,n,m,c,enm,hd[maxn];
struct edge{
	int v,nxt;
}e[maxn<<1];
il void addedge(int u,int v){
	e[++enm]=(edge){v,hd[u]};
	hd[u]=enm;
}
int dfn[maxn],low[maxn],cnt;
bool geb[maxn<<1];
il void tarjan(int u,int fa){
	dfn[u]=low[u]=++cnt;
	for(int i=hd[u],v;i;i=e[i].nxt){
		v=e[i].v;
		if(!dfn[v]){
			tarjan(v,i);
			low[u]=min(low[u],low[v]);
			if(low[v]>dfn[u]){
				geb[i]=geb[i^1]=1;
			}
		}
		else if(i!=fa&&i!=(fa^1)){
			low[u]=min(low[u],dfn[v]);
		}
	}
}
int bel[maxn],bcn,sz[maxn];
bool vis[maxn];
il void dfs1(int u){
	vis[u]=1,bel[u]=bcn,sz[bcn]++;
	for(int i=hd[u],v;i;i=e[i].nxt){
		v=e[i].v;
		if(!vis[v]&&!geb[i]){
			dfs1(v);
		}
	}
}
int dp[maxn][maxn][2],nf[maxn][maxn][2],tot;
vector<int> ed[maxn];
il void dfs2(int u,int fa){
	vis[u]=1;
	for(int v:ed[u]){
		if(v==fa){
			continue;
		}
		dfs2(v,u);
		sz[u]+=sz[v];
	}
}
il void upd(int &x,int y){
	x=min(x,y);
}
il void dfs3(int u,int fa,int rt){
	for(int v:ed[u]){
		if(v==fa){
			continue;
		}
		for(int i=0;i<=tot;i++){
			upd(nf[i+sz[v]][tot-i+sz[rt]-sz[v]][1],dp[i][tot-i][0]+2*i*sz[v]+sz[v]*sz[v]+2*(tot-i)*(sz[rt]-sz[v])+(sz[rt]-sz[v])*(sz[rt]-sz[v])+c*(i?1:0)+c*(tot-i?1:0));
			upd(nf[i+sz[rt]-sz[v]][tot-i+sz[v]][1],dp[i][tot-i][0]+2*i*(sz[rt]-sz[v])+(sz[rt]-sz[v])*(sz[rt]-sz[v])+2*(tot-i)*sz[v]+sz[v]*sz[v]+c*(i?1:0)+c*(tot-i?1:0));
		}
		dfs3(v,u,rt);
	}
}
il void solve(){
	n=read(),m=read(),c=read();
	enm=1;
	for(int i=1,u,v;i<=m;i++){
		u=read(),v=read();
		addedge(u,v);
		addedge(v,u);
	}
	cnt=0;
	for(int i=1;i<=n;i++){
		if(!dfn[i]){
			tarjan(i,0);
		}
	}
	bcn=0;
	for(int i=1;i<=n;i++){
		if(!vis[i]){
			bcn++;
			dfs1(i);
		}
	}
//	for(int i=1;i<=bcn;i++){
//		cout<<sz[i]<<" ";
//	}
//	puts("");
	for(int u=1;u<=n;u++){
		for(int i=hd[u],v;i;i=e[i].nxt){
			v=e[i].v;
			if(bel[u]!=bel[v]){
				ed[bel[u]].pb(bel[v]);
				ed[bel[v]].pb(bel[u]);
			}
		}
	}
	for(int i=1;i<=bcn;i++){
		sort(ed[i].begin(),ed[i].end());
		ed[i].erase(unique(ed[i].begin(),ed[i].end()),ed[i].end());
	}
	mem(dp,0x3f);
	dp[0][0][0]=0;
	tot=0;
	mem(vis,0);
	for(int i=1;i<=bcn;i++){
		if(!vis[i]){
//			cout<<i<<"\n";
			dfs2(i,0);
			memcpy(nf,dp,sizeof dp);
			for(int j=0;j<=tot;j++){
				upd(nf[j+sz[i]][tot-j][0],dp[j][tot-j][0]+2*j*sz[i]+sz[i]*sz[i]+c*(j?1:0));
				upd(nf[j][tot-j+sz[i]][0],dp[j][tot-j][0]+2*(tot-j)*sz[i]+sz[i]*sz[i]+c*(tot-j?1:0));
				upd(nf[j+sz[i]][tot-j][1],dp[j][tot-j][0]+2*j*sz[i]+sz[i]*sz[i]+c+c*(j?1:0));
				upd(nf[j+sz[i]][tot-j][1],dp[j][tot-j][1]+2*j*sz[i]+sz[i]*sz[i]+c*(j?1:0));
				upd(nf[j][tot-j+sz[i]][1],dp[j][tot-j][0]+2*(tot-j)*sz[i]+sz[i]*sz[i]+c+c*(tot-j?1:0));
				upd(nf[j][tot-j+sz[i]][1],dp[j][tot-j][1]+2*(tot-j)*sz[i]+sz[i]*sz[i]+c*(tot-j?1:0));
			}
			dfs3(i,0,i);
			tot+=sz[i];
			memcpy(dp,nf,sizeof nf);
		}
	}
//	cout<<tot<<"\n";
	int ans=inf;
	for(int i=1;i<tot;i++){
		ans=min(ans,dp[i][tot-i][1]);
	}
	write(ans>=inf?-1:ans);
	mem(hd,0),mem(dfn,0),mem(low,0);
	mem(vis,0),mem(geb,0),mem(sz,0);
	for(int i=1;i<=bcn;i++){
		ed[i].clear();
	}
}
namespace cplx{
	bool end;
	il double usdmem(){return (&begin-&end)/1048576.0;}
}
signed main(){
	T=read();
	while(T--){
		solve();
	}
	IO::flush();
	return 0;
}
}
signed main(){return asbt::main();}
/*
1
6 6 2
1 4
2 5
3 6
1 5
3 5
6 5
*/

标签:fa,int,void,vis,2025,maxn,mem,dp,刷题
From: https://www.cnblogs.com/zhangxyhp/p/18687374

相关文章

  • 2025春招 SpringCloud 面试题汇总
    大家好,我是V哥。SpringCloud在面试中属于重灾区,不仅是基础概念、组件细节,还有高级特性、性能优化,关键是项目实践经验的解决方案,都是需要掌握的内容,正所谓打有准备的仗,秒杀面试官,如果你正在准备这一块内容,V哥整理的以下面试题及答案,可能在2025年SpringCloud面试中出现,......
  • 桌面便签备忘录哪个好用?2025六大好用电脑桌面便签app推荐
    在日常工作和生活中,一款好用的桌面便签备忘录软件能够极大地提升我们的效率。它不仅能帮助我们记录重要事项,还能设置提醒,确保我们不会错过任何重要事件。今天,就为大家推荐六款在2025年备受好评的电脑桌面便签app!一、stickynotesWindows系统自带的便签工具,支持用户在桌面上创建......
  • 2025版大模型AI产品经理学习路线:零基础到精通,超详细解析,收藏这一篇就够了!
    随着人工智能技术的发展,尤其是大模型(LargeModel)的兴起,越来越多的企业开始重视这一领域的投入。作为大模型产品经理,你需要具备一系列跨学科的知识和技能,以便有效地推动产品的开发、优化和市场化。以下是一份详细的大模型产品经理学习路线,旨在帮助你构建所需的知识体系,从零基......
  • 2025年软件开发工作总结
    一、工作概述2025年,我全身心投入到软件开发工作中,主要使用C#和C++编程语言,结合WPF、Winform、Qt等开发框架,完成了多项重要软件项目,包括OFD阅读器和视频监控系统等。这一年,我在技术能力、项目管理以及团队协作方面都取得了显著进步,为公司的发展贡献了自己的力量。二、项目成果......
  • 【2025-01-22】连岳摘抄
    20:00如果你一天只说一句祈祷,请说“谢谢你”。                                                 ——鲁米一是分清主次。有些任务,时间等不了的,要先做。比如生孩子。......
  • 日常刷题2025-1-23
    日常刷题2025-1-23D.InaccurateSubsequenceSearchrating:1400https://codeforces.com/problemset/problem/1955/D思路(定长滑动窗口)定长滑动窗口,r只管加,l只管减即可。代码#include<bits/stdc++.h>typedefstd::pair<longlong,longlong>pll;typedefstd::pa......
  • 202511读书笔记|《山中与诸道友夜坐闻》——风翻荷叶一向白,雨湿蓼花千穗红
    202511读书笔记|《山中与诸道友夜坐闻》——风翻荷叶一向白,雨湿蓼花千穗红《山中与诸道友夜坐闻》温庭筠,还不错,可以轻松的读的小诗词。上学学过他的一些词,喜欢是缘于后来看花间集和飞花令。半小时可读完的一本书......
  • 洛谷OI_树的刷题笔记
    整个笔记注意力惊人,慎入......持续更新。P2700逐个击破能卡住我的黄题已经很少见了,但这道题确实又是一个。唉,只能说自己依然是蒟蒻吧。不过,由于题目很容易理解,加上自己因为刷难题身心俱疲,“玩”一下这种简单的题目也算是种放松。不能因为刷题,把自己学算法的乐趣搞没了。先......
  • 2025-1-20-盒子模型-弹性盒子模型
    重新学一下巩固,之前发的看不了,本来还想着直接看呢盒子模型width,height是宽高,padding是内边距,如果里边有文本的话一般是贴着左上方,但是有内边距就不会,类似下边的演示图;border是内外之间边框,就是给宽高之外加一层;margin是外边距,可以理解为是你构造的边框距离这个页面的距离div{......
  • 2025.1.22随笔
    前言本来想留很多时间慢慢写的,但是死人抛硬币让我做一晚上(((前几天没什么好说的,就是一直在恶补数学。我是从最基础的开始,然后这段时间只把数论通关了;组合还有东西没处理完;线代也还有许多要补。但是我还是写了十多道蓝以上的题,感觉数学中要考的知识点还是涵盖了许多吧(?)昨天VP了......