【UVA12083】Guardian of Decency

題意

  有N 個人,每個人有四個屬性:WSexMuSp
  兩個人uv 不能出現在同一個集合當且僅當滿足:
  |WuWv|40SexuSexv
  Muu=MuvSpuSpv
  問最多可以選出多少人使得這些人在同一個集合
  N500 ,最多100組數據

解法

二分圖最大匹配:
  這道題有兩種思考方向:
  ①.不排斥的人之間連邊,那麼問題轉化爲求最大團,很麻煩,不作考慮
  ②.排斥的人之間連邊,那麼問題轉化爲求最大獨立集,比較簡單,所以我們採取此種方法
  最大獨立集一般只有樹的最大獨立集和二分圖的最大獨立集兩種,本題顯然不可能是樹,於是考慮怎麼構建二分圖
  很明顯,因爲Sex 屬性只有兩種(不是男,就是女),所以可以按照Sex 將圖分爲兩個部分,然後再根據另外三個條件進行連邊(本題的N 比較小,所以使用矩陣方便一些)
  然後就是要求最大獨立集了,這裏有一個結論:二分圖的最大獨立集=總點數-最小覆蓋數,二分圖的最小覆蓋數=最大匹配
  (證明請看博客:http://blog.csdn.net/techmonster/article/details/50011363
  所以使用匈牙利算法求出最大匹配即可

複雜度

O(TN|E|

代碼

#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<map>
#define Rint register int
#define Lint long long int
using namespace std;
const int INF=0x3f3f3f3f;
const int E=100010;
const int N=510;
bool g[N][N],vis[N],sex[N];
int match[N],w[N];
int mu[N],cntm;
int sp[N],cnts;
int T,n,cnt;
map<string,int> f,v;
int abs(Rint x)
{
    return x<0 ? -x : x ;
}
bool find(Rint k)
{
    for(Rint i=1;i<=n;i++)
        if( !vis[i] && g[k][i] )
        {
            vis[i]=1;
            if( !match[i] || find( match[i] ) )
            {
                match[i]=k;return true ;
            }
        }
    return false ;
}
int main()
{
    char cs,a[N],b[N];
    scanf("%d",&T);
    while( T-- )
    {
        cnt=cntm=cnts=0;
        f.clear(),v.clear();
        scanf("%d",&n);
        for(Rint i=1;i<=n;i++)
        {
            scanf("%d %c%s%s",&w[i],&cs,a,b);
            if( !f[a] )   f[a]=++cntm;
            if( !v[b] )   v[b]=++cnts;
            mu[i]=f[a],sp[i]=v[b];
            sex[i]=(cs=='M');
            match[i]=0;
        }
        for(Rint i=1;i<=n;i++)
            for(Rint j=i+1;j<=n;j++)
                if( sex[i]==sex[j] || abs( w[i]-w[j] )>40 || mu[i]!=mu[j] || sp[i]==sp[j] )   g[i][j]=g[j][i]=0;
                else   g[i][j]=g[j][i]=1;
        for(Rint i=1;i<=n;i++)
        {
            for(Rint j=1;j<=n;j++)   vis[j]=0;
            if( find( i ) )   cnt++;
        }
        printf("%d\n",n-cnt/2);
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章