[匈牙利-二分图多重匹配]Gym-101873F 三排插问题

https://vjudge.net/contest/259384#status/Alice_and_Bob/F/0/

 

N个电器M个插座,可以把其中一个变成3插。问最多可以使用多少电器。

1.最大匹配

2.对每个插座分别尝试再找两条增广路,记录最多可以找到的个数(可能是0,1,2)。对每个插座尝试后,将匹配信息恢复成step1结束后的样子。

 

AC代码:

#include
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
*/

 

你可能感兴趣的:(二分图)