训练第十周

文章讲述了如何使用二分匹配、匈牙利算法和并查集的数据结构解决两个编程题目,涉及深度优先搜索(DFS),以及如何将模板题思路应用到实际问题中。
摘要由CSDN通过智能技术生成

p3386

突然觉得代码量少的简单了许多()

标准的二分匹配啦,只会匈牙利();

看代码更易懂()

#include<bits/stdc++.h>
using namespace std;
int n,m,e;
int maps[600][600];
int vis[600];
int match[600];
bool dfs(int x)
{
	for(int i=1;i<=m;i++)
	{
		if(!vis[i]&&maps[x][i])
		{
			vis[i]=1;
			if(!match[i]||dfs(match[i]))
			{
//				cout<<x<<" "<<i<<endl;
				match[i]=x;
				return true;
			}
		}
	}
	return false;
}
int ans;
int main()
{
	cin>>n>>m>>e;
	for(int i=0;i<e;i++)
	{
		int u,v;
		cin>>u>>v;
		maps[u][v]=1;
	}
	for(int i=1;i<=n;i++)
	{
		if(dfs(i))ans++;
		memset(vis,0,sizeof(vis));
	}
	cout<<ans;
	return 0;
}

p1525

这个题我说不上来怎么回事emmm,就是并查集?

#include<bits/stdc++.h>
using namespace std;
struct edge{int start,final,value;};
int n,m,father[20001],vis[20001];
edge arr[100005];
bool cmp(edge a,edge b)
{
	return a.value>b.value;	
}
int find(int x)
{
	if(father[x]==x)return x;
	father[x]=find(father[x]);
	return father[x];
}
void join(int x,int y)
{
	x=find(father[x]);
	y=find(father[y]);
	father[x]=y;
}
bool check(int x,int y)
{
	x=find(father[x]);
	y=find(father[y]);
	if(x==y)return true;
	return false;
}
int main()
{
	cin>>n>>m;
	for(int i=1;i<=n;i++)father[i]=i;
	for(int i=1;i<=m;i++)cin>>arr[i].start>>arr[i].final>>arr[i].value;
	sort(arr+1,arr+m+1,cmp);
	for(int i=1;i<=m+1;i++)
	{
		if(check(arr[i].start,arr[i].final))
		{
			cout<<arr[i].value;
			break;
		}
		else
		{
			if(!vis[arr[i].start])vis[arr[i].start]=arr[i].final;
			else join(vis[arr[i].start],arr[i].final);
			if(!vis[arr[i].final])vis[arr[i].final]=arr[i].start;
			else join(vis[arr[i].final],arr[i].start);
		}
	}
	return 0;
}

p1129

变相的二分匹配()

相当于一个模板题的变形,有了思路就很好写了

每一行有几个一,就有几个边,每个一对应的列标就是这条边的终点,每一行就是这条边的起点

如果有一行没有匹配到

就直接No,然后下一个循环

如果走完了一遍循环都匹配到了

那就输出Yes

甚至我是直接套的模板题的代码

#include<bits/stdc++.h>
using namespace std;
int maps[600][600];
int vis[600];
int match[600];
int m;
void read()
{
	memset(match,0,sizeof(match));
	cin>>m;
	for(int i=1;i<=m;i++)
	{
		for(int j=1;j<=m;j++)
		{
			int tem;
			cin>>tem;
			if(tem)maps[i][j]=1;
			else maps[i][j]=0;
		}
	}
}
bool dfs(int x)
{
	for(int i=1;i<=m;i++)
	{
		if(!vis[i]&&maps[x][i])
		{
			vis[i]=1;
			if(!match[i]||dfs(match[i]))
			{
//				cout<<x<<" "<<i<<endl;
				match[i]=x;
				return true;
			}
		}
	}
	return false;
}
int main()
{
	int n;
	cin>>n;
	for(int i=0;i<n;i++)
	{
		bool flag=true;
		read();
		for(int i=1;i<=m;i++)
		{
			if(!dfs(i))
			{
				flag=false;
			}
			memset(vis,0,sizeof(vis));
		}
		if(flag)
		{
			cout<<"Yes"<<endl;
		}
		else
		{
			cout<<"No"<<endl;
		}
	}
	return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值