LA 3415 ( 二分图匹配求最大点独立集 )

题意: 四个条件  第一  身高相差40以上  第二  性别不同  第三  喜欢的音乐不同  第四  喜欢的运动相同 满足一个  就可以同时去郊游否则不可以。 问最多去多少人?

思路: 我们将男女分开来 就可以建出一个二分图,对于任意的男女生  只要上边四个条件一个也不满足 就表示不能同时去 ,那么我们在其中间连一条边,那么最终的结果就是我们从中取出尽量多的点,使得任意两个点之间没有连线。那么问题就转化成了求最大点独立集。  二分图的最大点独立集=  总点数 -  最大匹配(最小点覆盖)。

代码: 

#include<bits/stdc++.h>

using namespace std;
const int N =505;

struct node
{
    int h;
    string mus;
    string ball;
};

node _nan[N],_nv[N];

vector<int >ve[N];
int boy[N],girl[N];
int ntot,vtot;
int vis[N];

int dfs(int u)
{
    for(int i=0;i<ve[u].size();i++)
    {
        int v=ve[u][i];
        if(!vis[v]){
            vis[v]=1;
            if( girl[v]==-1||dfs(girl[v]) ){
                girl[v]=u;
                boy[u]=i;
                return 1;
            }
        }
    }
    return 0;
}

void xiongyali()
{
    int cnt=0;
    for(int i=1;i<=ntot;i++)
    {
        memset(vis,0,sizeof(vis));
        if(dfs(i)) cnt++;
    }
    printf("%d\n",ntot+vtot-cnt);
}

int jud(int i,int j)
{
    int h=abs(_nan[i].h-_nv[j].h);
    if(h>40) return 0;
    if(_nan[i].mus!=_nv[j].mus) return 0;
    if(_nan[i].ball==_nv[j].ball) return 0;
    return 1;// 两个人不允许同时去。 所以在两个之间建一条边 求最大点独立集
    // 也就是 我们取出的图中的任意两个点 不能有边相连
}

int n;

int main()
{
    int T;
    node tmp;
    scanf("%d",&T);
    while(T--)
    {
        cin>>n;
        string op;
        for(int i=1;i<=n;i++ ) ve[i].clear();
        ntot=vtot=0;
        for(int i=1;i<=n;i++)
        {
            cin>>tmp.h>>op>>tmp.mus>>tmp.ball;
            if(op[0]=='M') _nan[++ntot]=tmp;
            else _nv[++vtot]=tmp;
        }
        memset(boy,-1,sizeof(boy));
        memset(girl,-1,sizeof(girl));

        for(int i=1;i<=ntot;i++)
        {
            for(int j=1;j<=vtot;j++)
            {
                if(jud(i,j)) ve[i].push_back(j);
            }
        }

        xiongyali();

    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/yjt9299/article/details/81089423
LA
今日推荐