1. 程式人生 > >訓練指南 UVALive - 3415(最大點獨立集)

訓練指南 UVALive - 3415(最大點獨立集)

ring == out 就是 http title cin != 我們


layout: post
title: 訓練指南 UVALive - 3415(最大點獨立集)
author: "luowentaoaa"
catalog: true
mathjax: true
tags:
- 二分圖
- 圖論
- 訓練指南


Guardian of Decency

UVALive - 3415

我們將男女分開來 就可以建出一個二分圖,對於任意的男女生 只要上邊四個條件一個也不滿足 就表示不能同時去 ,那麽我們在其中間連一條邊,那麽最終的結果就是我們從中取出盡量多的點,使得任意兩個點之間沒有連線。那麽問題就轉化成了求最大點獨立集。 二分圖的最大點獨立集= 總點數 - 最大匹配(最小點覆蓋)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=998244353;
const int maxn=1e3+50;
const ll inf=1e10;
const ll INF = 1000000000;
const double eps=1e-5;
#define bug cout<<"bbibibibbbb="<<endl;
/// 二分圖最大基數匹配
struct BPM{
    int n,m;    /// 左右頂點個數
    int G[maxn][maxn]; /// 鄰接表
    int left[maxn];    /// left[i]為右邊第i個點的匹配點編號,-1表示不存在
    bool T[maxn];       /// T[i]為右邊第i個點是否已標記

    int right[maxn];        /// 求最小覆蓋用
    bool S[maxn];           /// 求最小覆蓋用

    void init(int n,int m){
        this->n=n;
        this->m=m;
        memset(G,0,sizeof(G));
    }

   /* void AddEdge(int u,int v){
        G[u].push_back(v);
    }*/

    bool match(int u){
        S[u]=true;
        for(int v=0;v<m;v++){
            //int v=G[u][i];
            if(G[u][v]&&!T[v]){
                T[v]=true;
                if(left[v]==-1||match(left[v])){
                    left[v]=u;
                    right[u]=v;
                    return true;
                }
            }
        }
        return false;
    }
    /// 求最大匹配
    int solve(){
        memset(left,-1,sizeof(left));
        memset(right,-1,sizeof(right));
        int ans=0;
        for(int u=0;u<n;u++){
            memset(S,0,sizeof(S));
            memset(T,0,sizeof(T));
            if(match(u))ans++;
        }
        return ans;
    }
    /// 求最小覆蓋。X和Y為最小覆蓋中的點集
    int mincover(vector<int>& X,vector<int>& Y){
        int ans=solve();
        memset(S,0,sizeof(S));
        memset(T,0,sizeof(T));
        for(int u=0;u<n;u++)
            if(right[u]==-1)match(u);
        for(int u=0;u<n;u++)
            if(!S[u])X.push_back(u);
        for(int v=0;v<n;v++)
            if(T[v])Y.push_back(v);
        return ans;
    }
};
BPM solver;
struct node{
    int h;
    string m,s;
    node(int h,string m,string s):h(h),m(m),s(s){}
};
bool ok(node a,node b){
    return abs(a.h-b.h)<=40&&a.m==b.m&&a.s!=b.s;
}
int R,C,N;
int main()
{
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);
    std::cout.tie(0);
    int t;
    cin>>t;
    while(t--){
        int n;
        cin>>n;
        vector<node>a,b;
        for(int i=0;i<n;i++){
            int h;string m,s,sex;
            cin>>h>>sex>>m>>s;
            if(sex[0]=='M')a.push_back(node(h,m,s));
            else b.push_back(node(h,m,s));
        }
        int x=a.size(),y=b.size();
        solver.init(x,y);
        for(int i=0;i<x;i++)
            for(int j=0;j<y;j++)
            if(ok(a[i],b[j]))solver.G[i][j]=1;
        cout<<x+y-solver.solve()<<endl;
    }
    return 0;
}

訓練指南 UVALive - 3415(最大點獨立集)