zoukankan      html  css  js  c++  java
  • 训练指南 UVALive


    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;
    }
    
    
  • 相关阅读:
    南阳ACM 题目811:变态最大值 Java版
    南阳ACM 题目811:变态最大值 Java版
    南阳ACM 题目517:最小公倍数 Java版
    南阳ACM 题目517:最小公倍数 Java版
    Jquery学习总结(4)——高效Web开发的10个jQuery代码片段
    Mysql学习总结(34)——Mysql 彻底解决中文乱码的问题
    MyBatis学习总结(19)——Mybatis传多个参数(三种解决方案)
    Git学习总结(10)——git 常用命令汇总
    Spring MVC学习总结(7)——Spring MVC整合Ehcache缓存框架
    Mysql学习总结(33)——阿里云centos配置MySQL主从复制
  • 原文地址:https://www.cnblogs.com/luowentao/p/10352370.html
Copyright © 2011-2022 走看看