HDU 3829 Cat VS Dog(最大独立集)

题目大意:
有n只猫,有m只狗。现在有P个学生去参观动物园。每个孩子有喜欢的动物和不喜欢的动物。假如他喜欢猫那么他就一定不喜欢狗(反之亦然)。
如果一个孩子喜欢一个动物,那么这个动物不会被移除,若是不喜欢则移除。现在管理员想知道移除哪些动物可以使最大数量的孩子高兴。
输入数据:
输入包含多组测试实例。
第一行是三个数字n, m, p.
接下来p行。
每行 CX, DX 代表他喜欢第X只猫,讨厌第X只狗(反之亦然)
 
题目思路:
构图思路:我们把所有人进行构图,如果两个人之间有矛盾就建立一条边。然后求最大独立集就行了
二分图的最大独立集 : 二分图的最大独立集=图的点数  -  最大匹配数 
可以这样理解,在总的点集中,去掉最少的点,使得剩下的点相互之间没有边。用最少的点去覆盖所有的边,也就是最小覆盖。
 
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
#include<vector>
#include<queue>
#include<cmath>
using namespace std;
#define INF 0x3fffffff
#define maxn 505
int n, m, p, P[maxn], color[maxn];///n只猫 m只狗 p个人
bool G[maxn][maxn], vis[maxn];///构图
vector<vector<int> > LikeDog;///喜欢第k只狗的人邻接表
vector<vector<int> > DisDog;///不喜欢这只够的人的集合
vector<vector<int> > LikeCat;///同上
vector<vector<int> > DisCat;

void Init()
{
    LikeDog.clear();
    LikeDog.resize(m+1);
    LikeCat.clear();
    LikeCat.resize(n+1);

    DisDog.clear();
    DisDog.resize(m+1);
    DisCat.clear();
    DisCat.resize(n+1);
    memset(G, false, sizeof(G) );
}

void MakeMap()
{
    for(int i=1; i<=m; i++)
    {
        int len1 = LikeDog[i].size();
        int len2 = DisDog[i].size();
        for(int j=0; j<len1; j++)
        {
            int v1 = LikeDog[i][j];
            for(int k=0; k<len2; k++)
            {
                int v2 = DisDog[i][k];
                G[v1][v2] = true;
                G[v2][v1] = true;
            }
        }
    }


    for(int i=1; i<=n; i++)
    {
        int len1 = LikeCat[i].size();
        int len2 = DisCat[i].size();
        for(int j=0; j<len1; j++)
        {
            int v1 = LikeCat[i][j];
            for(int k=0; k<len2; k++)
            {
                int v2 = DisCat[i][k];
                G[v1][v2] = true;
                G[v2][v1] = true;
            }
        }
    }
}
bool Find(int u)
{
    for(int i=1; i<=p; i++)
    {
        if(!vis[i] && G[u][i])
        {
            vis[i] = true;
            if(P[i] == -1 || Find(P[i]) )
            {
                P[i] = u;
                return true;
            }
        }
    }
    return false;
}
void DFS(int u,int Color)
{
    color[u] = Color;
    for(int i=1; i<=p; i++)
    {
        if(G[u][i] && !color[i])
        {
            DFS(i, -Color);
        }
    }
}

int solve()
{
    int ans = 0;
    memset(P, -1, sizeof(P));
    memset(color, 0, sizeof(color));

    for(int i=1; i<=p; i++)
    {
        if(color[i] == 0)
            DFS(i, 1);
    }
    for(int i=1; i<=p; i++)
    {
        memset(vis, false, sizeof(vis));
        if(color[i] == 1 && Find(i) )
            ans ++;
    }
    return p - ans;
}

int main()
{
    while(scanf("%d %d %d ",&n, &m, &p) != EOF)
    {
        char ch1, ch2;
        int a, b;
        Init();
        for(int i=1; i<=p; i++)
        {
            scanf("%c%d %c%d",&ch1, &a, &ch2, &b);
            getchar();
            if(ch1 == 'C')
            {
                LikeCat[a].push_back(i);
                DisDog[b].push_back(i);
            }
            else
            {
                LikeDog[a].push_back(i);
                DisCat[b].push_back(i);
            }
        }
        MakeMap();
        printf("%d\n", solve() );
    }
    return 0;
}

 

posted @ 2015-08-10 17:23  向前走丶不回首  阅读(205)  评论(0编辑  收藏  举报