最大二分匹配

时间:2018-10-24 05:15:25

标签: algorithm graph-theory graph-algorithm

目前最大的二分匹配算法是O(√VE)。

这是我要解决上述问题的算法: 给定两组S1和S2以及它们之间的E边。

步骤1:根据程度对S1和S2进行升序排序

第2步:按排序顺序选择集合中的元素,并将其分配给另一个集合中的下一个空闲元素,然后计算匹配次数。

第3步:在S1上执行第2步,然后在S2上执行。

第4步:最多进行第3步。

这使得算法的复杂度高于O(Vlog(V)+(V + E))。

我无法证明上述算法的正确性,因此任何人都可以帮助解决上面示例失败的任何反例,因为该算法无法解决spoj问题MATCHING,因此算法是错误的,但可以' t找出反例。

谢谢

#include<bits/stdc++.h>
#define ll long long int
using namespace std;


int main(){

    ll c,b,p;
    cin >> c >> b >> p;
    c+=1;
    b+=1;
    ll mx = max(c,b);
    c =mx;
    b =mx;
    vector<ll> adjcow[c];
    vector<ll> adjbull[b];

    for(ll i=0; i<p; i++){
        ll x,y;
        cin >> x >> y;
        adjcow[x].push_back(y);
        adjbull[y].push_back(x);
    }

    /*
    for(ll i=0; i<c; i++){
        cout << i << " ";
        for(auto x:adjcow[i])
            cout << x << " ";
        cout << "\n";
    }

    for(ll i=0; i<b; i++){
        cout << i << " ";
        for(auto x : adjbull[i])
            cout << x << " ";
        cout << endl; 
    }
    */

    vector<pair<ll, ll>> deg1(c);
    vector<pair<ll, ll>> deg2(b);


    for(ll i=0; i<c; i++){
        ll count = 0;
        for(auto x: adjcow[i])
            count++;
        deg1[i] = {count, i};
    }

    for(ll i=0; i<b; i++){
        ll count = 0;
        for(auto x: adjbull[i])
            count++;
        deg2[i] = {count,i};
    }

    sort(deg1.begin(), deg1.end());
    sort(deg2.begin(), deg2.end());

    vector<bool> isTaken1(c,0);
    vector<bool> isTaken2(b,0);

    /*
    for(ll i=0; i<c; i++)
        cout << deg1[i].first << " " << deg1[i].second  << ", ";

    cout << endl;

    for(ll i=0; i<b; i++) 
        cout << deg2[i].first <<" "<< deg2[i].second  << ", ";

    cout << endl;
    */

    ll ansCow =0;
    for(auto x:deg1){
        ll node = x.second;
        for(auto u: adjcow[node]){
            if(isTaken1[u]==0){
    //          cout << node << "-> " << u << "\n";
                isTaken1[u] = 1;
                ansCow++;
                break;
            }
        }
    }

    //cout << "\n\n";

    ll ansBull =0;
    for(auto x:deg2){
        ll node = x.second;
        for(auto u: adjbull[node]){
            if(isTaken2[u]==0){
    //          cout << node << "->" << u << "\n";
                isTaken2[u] = 1;
                ansBull++;
                break;
            }
        }
    }

    cout << max(ansCow, ansBull) << "\n";
}

输入::

5 4 6
5 2
1 2
4 3
3 1
2 2
4 4

1 个答案:

答案 0 :(得分:0)

下面显示了一个反例。请注意,每个节点的度数均为2,因此排序无效。从左到右连接时,如果1选择A,2选择B,则3将无法连接。因此结果为2。从右到左连接时,如果A选择1,B选择2,则C无法连接。结果再次为2。但是正确的结果是3,其中1连接到C,2连接到B,3连接到A。

enter image description here

该程序的输入为:

3 3 6
1 1
1 3
2 2
2 3
3 1
3 2