HDU-2768-Cat vs. Dog(最大独立集 好题)

题目
题意:在每一集中,猫和狗都有机会展示自己,然后观众投票决定哪些宠物应该留下来,哪些应该被迫离开。
每个观众都可以对两件事进行投票:一件宠物应该留在节目中,另一件宠物应该被扔出去。此外,基于人人都是爱猫者(即恨狗者)或爱狗者(即恨猫者)这一普遍事实,已决定每一票必须准确说出一只猫和一只狗的名字。
输入

第一行中有一个正数:测试用例的数量,最多100个。在每个测试用例之后:
一行有三个整数c, d, v (≤1 c, d≤100 v和0≤≤500):猫,狗,和选民。
v行,每个行有两个pet标识符。第一个是这个选民想要养的宠物,第二个是这个选民想要扔掉的宠物。宠物标识符以字符“C”或“D”开头,分别表示宠物是猫还是狗。标识符的其余部分是一个整数,给出宠物的数量(猫在1和c之间,狗在1和d之间)。例如,’’ D42’表示狗的数量为42。

输出

每testcase:
其中一行是满足节目要求的选民的最大可能数量。

Sample Input

2
1 1 2
C1 D1
D1 C1
1 2 4
C1 D1
C1 D1
C1 D2
D2 C1

Sample Output

1
3

二分图最大独立集。猫一个集合,狗一个集合。
将 like 这个猫的,hate 这个猫的,连起来。
将 hate 这给狗的,like 这个狗的,连起来。
只要有连起来的边。说明这两个观众的意愿冲突。
二分图的左边内部之间不会有冲突,右边内部之间不会有冲突。
可以很明显的看出来这个题是求一个最大独立集。

#include <cstdio>
#include <cstring>
#define m(a,b) memset(a,b,sizeof a)
#define sd(a) scanf("%d",&a)
#define sdd(a,b) scanf("%d%d",&a,&b
using namespace std;
const int N=500+5;
const int INF=0x3f3f3f3f;
int head[N],mt[N];
int vis[N],tot;
struct Edge{int to,nex;}edge[N*N];
struct node{int like,hate;}cat_lover[N],dog_lover[N];
void add(int from,int to)
{
    edge[++tot]=(Edge){to,head[from]};head[from]=tot;
}
int find_path(int x)
{
    for(int i=head[x];i;i=edge[i].nex)
    {
        int y=edge[i].to;
        if(!vis[y])
        {
            vis[y]=1;
            if(!mt[y]||find_path(mt[y]))
            {
                mt[y]=x;
                return 1;
            }
        }
    }
    return 0;
}
int alter(char *str)
{
    int x=0,dex=1,len=strlen(str);
    while(dex!=len)
    {
        x+=str[dex]-'0';
        x*=10;
        dex++;
    }
    return x/10;
}
int main()
{
    int T;
    sd(T);
    while(T--)
    {
        m(head,0),m(mt,0);
        tot=1;
        int n1,n2,m;
        scanf("%d%d%d",&n1,&n2,&m);
        int cnt1=0,cnt2=0;
        for(int i=1;i<=m;i++)
        {
            char s1[5],s2[5];
            scanf("%s%s",s1,s2);
            if(s1[0]=='C')
                cat_lover[++cnt1]=(node){alter(s1),alter(s2)};
            else
                dog_lover[++cnt2]=(node){alter(s1),alter(s2)};
        }
        for(int i=1;i<=cnt1;i++)
            for(int j=1;j<=cnt2;j++)
                if(dog_lover[j].hate==cat_lover[i].like||dog_lover[j].like==cat_lover[i].hate)
                    add(i,j);        //连边。
        int ans=0;
        for(int i=1;i<=cnt1;i++)
        {
            m(vis,0);
            if(find_path(i))
                ans++;
        }
        printf("%d\n",m-ans);
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值