二分图
讲了这么久数学头一直晕得很,总算有一个听得清楚明白的东西了。
先写一下,一会儿放个源码。
最大匹配:
#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;
}
頑張って

浙公网安备 33010602011771号