https://vjudge.net/contest/259384#status/Alice_and_Bob/F/0/
N个电器M个插座,可以把其中一个变成3插。问最多可以使用多少电器。
1.最大匹配
2.对每个插座分别尝试再找两条增广路,记录最多可以找到的个数(可能是0,1,2)。对每个插座尝试后,将匹配信息恢复成step1结束后的样子。
AC代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=3002;
const int maxm=75005;
int m,n,k,cnt;
int head[maxn],vis[maxn],match[maxn],mat2[maxn];
int rem1[maxn],rem2[maxn];
struct node{
int to,ne;
}e[maxm];
void add(int u,int v){
e[cnt].to=v;
e[cnt].ne=head[u];
head[u]=cnt++;
}
int dfs(int u){
for(int i=head[u];~i;i=e[i].ne){
int v=e[i].to;
if(!vis[v]){
vis[v]=1;
if(match[v]==-1||dfs(match[v])){
match[v]=u;
return 1;
}
}
}
return 0;
}
int main(){
scanf("%d%d%d",&m,&n,&k);//m个插座,n个电器
for(int i=1;i<=n+m;i++) head[i]=match[i]=mat2[i]=-1;
int a,b,ans=0;
for(int i=1;i<=k;i++){
scanf("%d%d",&b,&a);
add(b,a);
}
for(int i=1;i<=m;i++){
for(int j=1;j<=n;j++) vis[j]=0;
if(dfs(i)) ans++;
}
for(int i=1;i<=n;i++) mat2[i]=match[i];
int plu=0,tmp=0;
for(int i=1;i<=m;i++){
for(int j=1;j<=n;j++)match[j]=mat2[j],vis[j]=0;
tmp=0;
if(dfs(i)) tmp++;
if(dfs(i)) tmp++;
plu=max(plu,tmp);
if(plu>=2) break;
}
printf("%d\n",ans+min(plu,2));
return 0;
}
/*
1 4 4
1 1
1 2 1 3 1 4
*/