UValive 4288 (二分圖最大獨立集)

題目大意

有n個人,有c只貓與d只狗,每個人要麼喜歡一隻狗且討厭一隻貓,要麼喜歡一隻貓且討厭一隻狗,所以每個人都希望自己喜歡的被留下,自己討厭的被帶走,這樣這個人就會滿足,現在你需要找到一個貓狗集合方案,使得滿足的人儘量多,求最多的滿足人數。

思路

圖很大,且樣例很多,不能暴力建圖(就是每個人除了對自己討厭的東西之外都建邊),所以需要思維優化。可以這樣考慮,如果一個人喜歡的貓或狗是另一個人所討厭的,那麼這兩個人肯定不會同時滿足,用二分圖的思想就是一條邊不能同時選擇兩個端點。這樣,我們n^2暴力建二分圖,如果兩個人有衝突,在二分圖中建立邊i->j,這樣求出來就是二分圖最小覆蓋,他的反面就是我們要求的最大獨立集,也就是ans=n-最大匹配。

#include <bits/stdc++.h>
using namespace std;
const int maxn=500+10;

vector<int>G[maxn*2];
pair<string,string>P[maxn];
void init(int c,int d,int n){
    for(int i=0;i<=n;i++)
    {
        G[i].clear();
        P[i].first=P[i].second="";
    }

}
void Build(int n){
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            if(i==j)continue;
            if(P[i].first==P[j].second||P[i].second==P[j].first){
                G[i].push_back(j);
            }
        }
    }
}
int vis[maxn];
int link[maxn];
bool Find(int x)
{
    for(int i=0;i<G[x].size();i++)
    {
        int v=G[x][i];
        if(!vis[v])
        {
            vis[v]=true;
            if(link[v]==-1||Find(link[v]))
            {
                link[v]=x;
                return true;
            }
        }
    }
    return false;
}
int Hungery(int n)
{
    int ans=0;
    for(int i=1;i<=n;i++)
    {
        memset(vis,false,sizeof(vis));
        if(Find(i))
            ans++;
    }
    return ans;
}

signed main(){
    int T;
    scanf("%d",&T);
    while(T--){
        int c,d,v;
        scanf("%d%d%d",&c,&d,&v);
        init(c,d,v);
        for(int i=1;i<=v;i++){
            string s1,s2;
            cin>>s1>>s2;
            P[i]=make_pair(s1,s2);
        }
        Build(v);
        memset(link,-1,sizeof(link));
        int ans=Hungery(v);//最大匹配數
        printf("%d\n",v-ans/2);
    }
    return 0;
}

 

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