[匈牙利-二分圖多重匹配]Gym-101873F 三排插問題

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

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章