HDU1845ジミーの割り当て(ハンガリーのアルゴリズム)

トピックリンク

ジミーの割り当て

ジミーは彼の大学で高度なグラフアルゴリズムを勉強しています。彼の最近の任務は、特別な種類のグラフで最大の一致を見つけることです。このグラフは無向で、N個の頂点があり、各頂点の次数は3です。さらに、グラフは2辺連結です(つまり、グラフを切断するには、少なくとも2つの辺を削除する必要があります)。マッチングはグラフのエッジのサブセットであり、サブセット内の2つのエッジに共通の頂点がないようにします。最大マッチングとは、カーディナリティが最大のマッチングです。
上記の特別なグラフの一連のインスタンスを前提として、各インスタンスの最大一致のカーディナリティを見つけます。
————————————————
入力
入力の最初の行には、従うべきグラフ記述の数を表す整数Tが含まれています。各説明の最初の行には、頂点の数を表す偶数の整数N(4 <= N <= 5000)が含まれています。次の3 * N / 2行のそれぞれには、頂点Aと頂点Bの間にエッジがあることを示す1つの空白で区切られた2つの整数AとBが含まれます。頂点には1からNまでの番号が付けられます。入力。
————————————————
出力
Tグラフのそれぞれについて、入力で指定された順序で、最大一致のカーディナリティを含む1行を印刷します。
————————————————
サンプル入力
2
4
1 2
1 3
1 4
2 3
2 4
3 4
4
1 2
1 3
1 4
2 3
2 4
3 4
出力例
2
2

題名

N個の頂点を持つ無向の通常のグラフで、ポイントの各ペアにエッジが存在するように、できるだけ多くのポイントペアを見つけます。

アイデア

ポイントを2つのグループに分けて、一致する最大数を見つけます。無向であるため、エッジを2回追加する必要があります。TLを直接実行し始めたので、最適化のためにn個の頂点を2つのグループに分割しました(一方のポイントを選択している限り、もう一方のグループの対応するポイントを再度選択することはできないため、半分を使用して最大一致数を見つけます) 。

コード

#include<bits/stdc++.h>
using namespace std;
const int maxn=5005;
typedef long long ll;
const int inf=0x3f3f3f3f;
const int minn=0xc0c0c0c0;
bool ch[maxn];
vector<int> re[maxn];
int ed[maxn],m,n;
int find(int x)
{
    
    
    for(int i=0;i<re[x].size();i++)
    {
    
    
    	int v=re[x][i];
        if(!ch[v])//此点可选 
        {
    
    
            ch[v]=true;//标记为不可选 
            if(!ed[v]||find(ed[v])) 
            {
    
    
                ed[v]=x;
                return 1;
            }//若此点还未匹配或者已匹配的点还有其余选择 
        }
    }
    return 0;
} 
int main()
{
    
    
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    int a,b,t,sum;
    cin>>t;
    while(t--)
    {
    
    
        cin>>n;
        memset(ed,0,sizeof(ed));
        for(int i=0;i<n;i++)
        	re[i].clear();
        for(int i=0;i<3*n/2;i++)
        {
    
    
            cin>>a>>b;
            re[a].push_back(b);
            re[b].push_back(a);
        }//无向,需要两次添加 
        sum=0;
        for(int i=1;i<=n/2;i++)
        {
    
    
            memset(ch,false,sizeof(ch));
            if(find(i))
            	sum++;
        }//将n个顶点分为两组进行对应即可 
        cout<<sum<<endl;
    }
    return 0;
}

おすすめ

転載: blog.csdn.net/WTMDNM_/article/details/107640043