18-1-30~2~5一周算法总结(DP,二分图,最小生成树)

经典算法与数据结构解析
本文深入探讨了经典算法如01背包问题、最长上升子序列等的实现方法,并介绍了二分图匹配与最小生成树的构造算法。此外,还提供了详细的伪代码与注意事项。

30

DP(最长上升子序列和lcs)

摸了

1

DP(01背包和完全背包)

01背包

		for(int i=1;i<=n;i++){
			for(int j=k;j>=w[i];j--){
				dp[j]=max(dp[j-w[i]]+v[i],dp[j]);//维护对于第i个物品,不放的时候的最大值和放了之后空间减少w[i]的最大值 
			}
		}
完全背包和01背包基本一致,唯一的区别是从01是逆推但是完全是顺推(顺推就可以在已经放了本物品的基础上再次放)

		for(int i=1;i<=n;i++){
			for(int j=0;j<=m;j++){
				if(j>=w[i]){
					dp[j]=min(dp[j],dp[j-w[i]]+v[i]);
				}
			}
		}
对于那种可以在最后的空间插入更大的值的问题,可以一上来就把空间j的大小减x来达到。


3

二分图

2点,一个是区分是否二分图,一个是算二分图的最多匹配数。

是否二分可以很简单的用染色来判断。bfs遍历。

算匹配数用到匈牙利算法。核心代码如下。

邻接矩阵

int n,m;
int line[1000+5][1000+5],used[1000+5],nxt[1000+5] ;

bool Find(int x){
	for(int i=1;i<=m;i++){
		if(line[x][i]&&!used[i]){
			used[i]=1;
			if(nxt[i]==0||Find(nxt[i])){
				nxt[i]=x;
				return true;
			}
		}
	}
	return false;
} 

int match(){
	int all=0;
	for(int i=1;i<=n;i++){
		mem(used,0);
		if(Find(i)) all++;
	}
	return all;
}
邻接表

下次再补

PS:还有需要注意的一些细节

 1最大不相关个数=总个数-最大匹配个数

 2如果没有专门给你区分x来着左,y来自右,那么可以在构建的时候line[x][y]=1,line[y][x]=1,但是这样的话

最大匹配=match()/2;
 3其实给我们一个有向图,在做与1内容相关的题目的时候,我们可以近似的看成是无向图,不过是出发点是左,
终点是右,来计算。(也不是很懂,但是可以做)poj 1422
4最大匹配个数=(覆盖图的)最小顶点个数

5

最小生成树

需要并查集。

其次基本思想是套用kruskal算法,将边的花费保存,并按从小到大打排序,依次取出边,如果边的2个端点没有通路,则把这2个端点用这条边连起来。

代码

const int maxn=1e5+5;
int f[maxn];
struct edge{
	int x,y,cost;
} e[10005];
//int  rank[maxn]; 
void init(){//初始化// 
	for(int i=1;i<maxn;i++){
		f[i]=i;
//		rank[i]=0;
	}
}

int find(int x){//查找并优化到这条链上的所以结点都和根直接相连// 
	return f[x]==x?x:f[x]=find(f[x]);
}

void un(int x,int y){//连点// 未用rank优化,取消掉/则转变为rank优化// 
	int a=find(x);
	int b=find(y);
	if(a!=b){
//		if(rank[a]>rank[b])
			f[b]=a; 
/*		else{
			f[a]=b;
			if(rank[a]==rank[b])
				rank[a]++;
		}*/
	}
}

bool cmp(edge e1,edge e2){
	return e1.cost<e2.cost;
} 

int kruskal(){
	init();
	sort(e,e+m,cmp);
	int all=0;
	for(int i=0;i<m;i++){
		int x=e[i].x;
		int y=e[i].y;
		if(find(x)==find(y)) continue;
		un(x,y);
		all+=e[i].cost;
	}
	return all;
} 
PS:我这里是返回了最小生成树的边的长度。

非课程相关

突然知道的,

ll超过范围会自动取模啊,ull也是!

乐播投屏是一款简单好用、功能强大的专业投屏软件,支持手机投屏电视、手机投电脑、电脑投电视等多种投屏方式。 多端兼容与跨网投屏:支持手机、平板、电脑等多种设备之间的自由组合投屏,且无需连接 WiFi,通过跨屏技术打破网络限制,扫一扫即可投屏。 广泛的应用支持:支持 10000+APP 投屏,包括综合视频、网盘与浏览器、美韩剧、斗鱼、虎牙等直播平台,还能将央视、湖南卫视等各大卫视的直播内容一键投屏。 高清流畅投屏体验:腾讯独家智能音画调校技术,支持 4K 高清画质、240Hz 超高帧率,低延迟不卡顿,能为用户提供更高清、流畅的视觉享受。 会议办公功能强大:拥有全球唯一的 “超级投屏空间”,扫码即投,无需安装。支持多人共享投屏、远程协作批注,PPT、Excel、视频等文件都能流畅展示,还具备企业级安全加密,保障会议资料不泄露。 多人互动功能:支持多人投屏,邀请好友加入投屏互动,远程也可加入。同时具备一屏多显、语音互动功能,支持多人连麦,实时语音交流。 文件支持全面:支持 PPT、PDF、Word、Excel 等办公文件,以及视频、图片等多种类型文件的投屏,还支持网盘直投,无需下载和转格式。 特色功能丰富:投屏时可同步录制投屏画面,部分版本还支持通过触控屏或电视端外接鼠标反控电脑,以及在投屏过程中用画笔实时标注等功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值