二分图

讲了这么久数学头一直晕得很,总算有一个听得清楚明白的东西了。

先写一下,一会儿放个源码。

最大匹配:

#include
using namespace std;
#define N 114514
#define M 1919810
#define ll long long
ll n,m,k,a,b;
ll vis[501],p[N],ans;
typedef pair <ll,ll> pi;
map <pi, bool=""> ma;
bool dfs(ll u){
    for ( int i=1;i<=m;++i){
        if (vis[i]||!ma[make_pair(u,i)])  continue ;
        vis[i]=1;
        if (!p[i]||dfs(p[i])){
            p[i]=u;
            return 1;
        }
    }
    return 0;
}
int main(){
    cin>>n>>m>>k;
    for ( int i=1;i<=k;++i){
        cin>>a>>b;
        if (ma[make_pair(a,b)])  continue ;
        ma[(make_pair(a,b))]=1;
    }
    for ( int i=1;i<=n;++i){
        memset (vis,0, sizeof (vis));
        if (dfs(i)) ans++;
    }
    cout<</pi,></ll,ll>

 最小点覆盖(P7368):

#include
using namespace std;
#define N 114514
#define M 1919810
#define ll long long
ll n,m,k,a,b;
ll vis[501],p[N],ans;
typedef pair <ll,ll> pi;
map <pi, bool=""> ma;
bool dfs(ll u){
    for ( int i=1;i<=n;++i){
        if (vis[i]||!ma[make_pair(u,i)])  continue ;
        vis[i]=1;
        if (!p[i]||dfs(p[i])){
            p[i]=u;
            return 1;
        }
    }
    return 0;
}
int main(){
    cin>>n>>k;
    for ( int i=1;i<=k;++i){
        cin>>a>>b;
        ma[(make_pair(a,b))]=1;
    }
    for ( int i=1;i<=n;++i){
        memset (vis,0, sizeof (vis));
        if (dfs(i)) ans++;
    }
    cout<</pi,></ll,ll>

  最大权匹配KM算法(P1559 运动员最佳匹配问题):

#include<bits/stdc++.h>
using namespace std;
#define N 105
#define M 1919810
#define ll long long
#define inf 1e9+7
ll n,m,k,P[N][N],Q[N][N];
ll visx[N],visy[N],p[N],ans;
ll fx[N],fy[N],d[N];
bool dfs(ll u){
	visx[u]=1;
	for(int v=1;v<=n;++v){
		if(visy[v]) continue;
		ll t=fx[u]+fy[v]-P[u][v];
		if(t==0){ //加到相等子图 
			visy[v]=1;
			if(!p[v]||dfs(p[v])){
				p[v]=u;
				return 1;
			}
		}
		else d[v]=min(d[v],t);
	}
	return 0;
}
void getans(){ //KM 
	memset(p,0,sizeof(p));
	memset(fx,0,sizeof(fx));
	memset(fy,0,sizeof(fy));
	for(int i=1;i<=n;++i)
		for(int j=1;j<=n;++j)
			fx[i]=max(fx[i],P[i][j]);
	for(int i=1;i<=n;++i){
		while(1){
			memset(visx,0,sizeof(visx));
			memset(visy,0,sizeof(visy));
			memset(d,inf,sizeof(d));
			if(dfs(i)) break;
			ll minn=inf;
			for(int j=1;j<=n;++j)
				if(!visy[j]) minn=min(minn,d[j]); //在没有到达的点中取最小的d
			for(int j=1;j<=n;++j){
				if(visx[j]) fx[j]-=minn; //x部减去d
				if(visy[j]) fy[j]+=minn; //y部加上d 
			}
		}
	}
	ll res=0;
	for(int i=1;i<=n;++i){
		res+=fx[i];
		if(p[i]) res+=fy[i];
	}
	cout<<abs(res)<<'\n';
}
int main(){
	cin>>n;
	for(int i=1;i<=n;++i)
		for(int j=1;j<=n;++j)
			cin>>P[i][j];
	for(int i=1;i<=n;++i)
		for(int j=1;j<=n;++j)
			cin>>Q[i][j];
	for(int i=1;i<=n;++i)
		for(int j=1;j<=n;++j)
			P[i][j]=P[i][j]*Q[j][i];
	getans();
	return 0; 
}

 

posted @ 2023-05-06 10:52  和蜀玩  阅读(22)  评论(0)    收藏  举报