CRPweek10周报

P1525 [NOIP2010 提高组] 关押罪犯

1.思路:这道题只把罪犯放在两个监狱中,首先想到的是二分匹配算法,但后面发现并查集好做,我们只需用优先队列对罪犯间的怨恨值进行排序,怨恨值越高,我们需要优先把罪犯分别安排再两个监狱。并查集方式:敌人的敌人就是朋友。

2.代码:

#include <bits/stdc++.h>
using namespace std;
int fa[20005];
int b[20005];
int ans;
int z1;
int z2;
int n,m;
struct priority
{
	int x;
	int y;
	int c;
	bool operator <(const priority &x)const
	{
		return x.c>c;
	}
};
priority_queue<priority>q;
int find(int x)
{
	if(fa[x]==x)
	{
		return x;
	}
	else
	{
		fa[x]=find(fa[x]);
		return fa[x];
	}
}
void merge(int i,int j)
{
	fa[find(i)]=find(j);
}
void init()
{
	for(int i=1;i<=n;i=i+1)
	{
		fa[i]=i;
	}
}
int main()
{
	cin>>n>>m;
	init();
	for(int i=1;i<=m;i=i+1)
	{
		int u,o,p;
		cin>>u>>o>>p;
		q.push((priority){u,o,p});
	}
	while(!q.empty())
	{
		priority temp=q.top();
		q.pop();
		int x1=temp.x;
		int y1=temp.y;
		if(find(x1)==find(y1))
		{
			ans=temp.c;
			cout<<temp.c<<endl;
			break;
		}
		else
		{
			if(!b[x1])
			{
				b[x1]=y1;
			}
			else
			{
				merge(b[x1],y1);
			}
			if(!b[y1])
			{
				b[y1]=x1;
			}
			else
			{
				merge(b[y1],x1);
			}
		}
	}
	if(ans==0)
	{
		cout<<0;
	}
}

P3386 【模板】二分图最大匹配

1.思路:没啥好说的,代模板就对了

2.代码:

#include <bits/stdc++.h>
using namespace std;
int n,m,e;
int g[505][505];
int linker[505];
bool used[505];
bool dfs(int u)
{
	for(int v=1;v<=m;v=v+1)
	{
		if(g[u][v]&&!used[v])
		{
			used[v]=1;
			if(linker[v]==-1||dfs(linker[v]))
			{
				linker[v]=u;
				return true;
			}
		}
	}
	return false;
}
int hungary()
{
	int res=0;
	memset(linker,-1,sizeof(linker));
	for(int u=1;u<=n;u++)
	{
		memset(used,false,sizeof(used));
		if(dfs(u))
		{
			res++;
		}
	}
	return res;
}
int main()
{
	cin>>n>>m;
	cin>>e;
	for(int i=1;i<=e;i=i+1)
	{
		int u,v;
		cin>>u>>v;
		g[u][v]=1;
	}
	cout<<hungary()<<endl;
}

P1129 [ZJOI2007] 矩阵游戏

1.思路:这个二分图感觉好隐蔽,因为每一个对角线都需要是黑色的,说明每一个列集合中的点都需要与每一个行集合的点匹配,然后换行和换列就是改变点的位置,不影响匹配,所以我们只需进行一次最大匹配搜索就可以了。

2.代码:

#include <bits/stdc++.h>
using namespace std;
int n,m;
int g[205][205];
int linker[205];
bool used[205];
bool dfs(int u)
{
	for(int v=1;v<=m;v=v+1)
	{
		if(g[u][v]&&!used[v])
		{
			used[v]=1;
			if(linker[v]==-1||dfs(linker[v]))
			{
				linker[v]=u;
				return true;
			}
		}
	}
	return false;
}
int hungary()
{
	int res=0;
	memset(linker,-1,sizeof(linker));
	for(int u=1;u<=n;u++)
	{
		memset(used,false,sizeof(used));
		if(dfs(u))
		{
			res++;
		}
	}
	return res;
}
int main()
{
	int t;
	cin>>t;
	for(int i=1;i<=t;i=i+1)
	{
		cin>>n;
		m=n;
		for(int j=1;j<=n;j=j+1)
		{
			for(int k=1;k<=n;k=k+1)
			{
				cin>>g[j][k];
			}
		}
		if(hungary()==n)
		{
			cout<<"Yes"<<endl;
		}
		else
		{
			cout<<"No"<<endl;
		}
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值