NEUQ-ACM预备队必做题07

P1525 [NOIP2010 提高组] 关押罪犯

并查集

#include<bits/stdc++.h>

#define f(i,a,b) for(int (i)=(a);(i)<=(b);++i)

using namespace std;
const int N=20005;
int n,m,L;
int ob[N],root[N]; 
struct linker{
	int x,y,v;
};
inline int read()
{
	int t=1,ans=0;
	char x=getchar();
	while(x<'0'||x>'9'){
		if(x=='-') t=-1;
		x=getchar();
	}
	while(x>='0'&&x<='9'){
		ans=ans*10+x-'0';
		x=getchar();
	}
	return ans*t;
} 
bool cmp(const linker x,const linker y)
{
	return x.v>y.v;
}
int fa(const int x)
{
	if(x!=root[x])
		root[x]=fa(root[x]);
	return root[x];
}
inline void add(const int x,const int y)
{
	int f1=fa(x),f2=fa(y);
	if(f1!=f2)
		root[f2]=f1;
	return;
} 
int main()
{
	linker a[100005]; 
	n=read(),L=read();
	f(i,1,n)
		root[i]=i;
	f(i,1,L){
		a[i].x=read(),a[i].y=read(),a[i].v=read();
	}
	sort(a+1,a+1+L,cmp);
	f(i,1,L){
		if(fa(a[i].x)==fa(a[i].y)){
			cout<<a[i].v;
			return 0; 
		}
		if(!ob[a[i].x]) ob[a[i].x]=a[i].y; 
		else add(ob[a[i].x],a[i].y);
		if(!ob[a[i].y]) ob[a[i].y]=a[i].x;
		else add(ob[a[i].y],a[i].x);
	}
	cout<<0;
	return 0;
}

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

匈牙利算法

#include<bits/stdc++.h>
#define ll long long
#define lowbit(x) (x)&(-x)
#define f(i,a,b) for(int (i)=(a);(i)<=(b);++i)
#define Ma(x,y) make_pair((x),(y))
#define mem0(x) memset((x),0,sizeof(x)) 
using namespace std;
const int N=2001;
int n,m,L;
int ink[N][N];
int used[N],vis[N];
int ans=0;

bool dfs(const int x)
{
	f(i,1,m){
		if(vis[i] || !ink[x][i]) continue;
		vis[i]=1;
		if(used[i]==0 || dfs(used[i])){
			used[i]=x;
			return 1; 
		}	 	
	}
	return 0;
}

int main()
{
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	cin>>n>>m>>L;
	f(i,1,L){
		int a,b;
		cin>>a>>b;
		if(a>n||b>m||a<1||b<1)  continue;
		ink[a][b]=1; 
	}
	f(i,1,n){
		mem0(vis);
		if(dfs(i))		++ans;
	}
	cout<<ans;
	return 0;
}

 P1129 [ZJOI2007] 矩阵游戏

必须每行每列都有才可能完成,易得即使每行每列都有也不一定可以完成。每一行都必须去对应,也就是说每一行通过行变化要对应某一列(变成了新的矩阵,不用担心变化对原来矩阵的影响),匈牙利算法。

#include<bits/stdc++.h>
#define ll long long
#define lowbit(x) (x)&(-x)
#define f(i,a,b) for(int (i)=(a);(i)<=(b);++i)
#define Ma(x,y) make_pair((x),(y))
#define mem0(x) memset((x),0,sizeof(x)) 
using namespace std;
const int N=401;
int n;
int ans=0;
int b[N],c[N];
int cnt=0,nex[N*N],to[N*N],fr[N];
int used[N],lin[N];
inline void clear()
{
	f(i,1,cnt)
		nex[i]=to[i]=0;
	f(i,1,n)
		fr[i]=0;
	return;	
}
inline void add(int x,int y)
{
	++cnt;
	nex[cnt]=fr[x];
	fr[x]=cnt;
	to[cnt]=y;
} 
inline bool dfs(const int x)
{
	for(int i=fr[x];i;i=nex[i]){
		if(used[to[i]]) continue;
		used[to[i]]=1;
		if(lin[to[i]]==0 || dfs(lin[to[i]])){
			lin[to[i]]=x;
			return 1;
		}
	}
	return 0;
}
inline bool check()
{
	mem0(lin);
	f(i,1,n){
		mem0(used);
		if(!dfs(i))	return 0;
	}
	return 1; 		
}

int main()
{
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	int T;
	cin>>T;
	while(T--)
	{
		clear();
		cin>>n;
		f(i,1,n)
		  f(j,1,n){
		  	int a;
		  	cin>>a;
		  	if(a==1){
		  		add(i,j); 
			  }
		  }  
		if(check()) cout<<"Yes\n";   
		else	cout<<"No\n";    
	}
	
	return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值