NKOJ 1979 投票

来源:互联网 发布:python numpy 编辑:程序博客网 时间:2024/05/18 01:21

问题描述

小 k 同学正在玩一个游戏,在游戏中他扮演了一个马戏团的老板,现在小 k同学需要利用马戏团中的A只猫和B只狗举办一次表演,表演之前他让观众进行了投票,投票的类容是:
我想看到第号猫/狗的表演,不想看到第号猫/狗的表演。注意到每个观众都是更喜欢猫或更喜欢狗,所以两个空后面一定会被勾上不同的内容。喜欢猫的观众会在第一空后面选择猫,第二空后面选择狗;反之就会在第一空后面选择狗,第二空后面选择猫。对于每一个观众,只有当 TA投票的内容都被满足了(即 TA想看到的动物出场表演,TA不想看到的动物不参与表演)的时候,TA才会来看表演。当然啦,看表演是要付门票钱的,作为马戏团的老板,小 k自然是希望来的人越多越好了。他想找到一个安排动物表演的方案,使得来看表演的观众尽量多。


输入格式

第1行 3 个正整数n、m、k,分别表示猫、狗和观众的数量
第2~k + 1行,每行描述了一个观众的投票内容。
首先输入一个字符 C或 D紧接着是一个数字,表示某个观众想看到的动物,然后是一个空格隔开,接下去又是一个 C或 D 加上一个数字,表示这个观众不想看到的动物,同一行中一定不会出现两个 C或两个 D。


输出格式

输出一行一个正整数,表示小 k在最优的安排下可以吸引多少观众来看表演。


样例输入

1 2 4
C1 D1
C1 D1
C1 D2
D2 C1


样例输出

3


数据范围

对于 25%的数据,n,m ≤ 10, k ≤ 25 ;
对于 100%的数据,n,m ≤ 300, k ≤ 500.


看到这道题吧,要使两个集合之间不能产生冲突,我们很容易想到了二分图匹配的方法。
但需要注意的是这道题的二分图构建方法。
我最初的想法是猫狗为一整体,上下两层,也就是上面为n+m个点,下面为n+m个点,然后通过边来描述他们之间的对应关系。
但后来发现并不行==因为无法描述同时讨厌和喜欢。
于是我们应该换一种构图方法:
把喜欢猫的人放上面,喜欢狗的人放下面。当一条边的两边出现该情况:喜欢猫的这个人讨厌的狗正好是喜欢这条狗的人讨厌的猫(也就是产生了冲突),我们把这两个点之间进行连边。
最后要求我们求出最大能满足多少人,也就是用总人数-最大匹配数就可以了。
附上拙劣代码==其实就是一道裸的二分图,就是建图稍微有一点麻烦而已啦

#include<iostream>#include<cstring>using namespace std;bool road[1005];int n,m,k;int map[1005][1005],link[1005];int c[1005],d[1005],disc[1005],disd[1005],s1[1005],s2[1005];char a,b;int x,y;int ans=0;int cntc,cntd;bool find(int v){      for(int i=1;i<=k;i++)          if(map[v][i]&&(!road[i])){              road[i]=true;              if(!link[i]||find(link[i])){                  link[i]=v;                  return true;              }          }      return false;  }  int main(){       cin>>n>>m>>k;    for(int i=1;i<=k;i++)    {        cin>>a>>x;        cin>>b>>y;        if(a=='C')        {            s1[++cntc]=i;            c[i]=x;            disd[i]=y;        }        else         {            s2[++cntd]=i;            d[i]=x;            disc[i]=y;        }     }    for(int i=1;i<=cntc;i++)    for(int j=1;j<=cntd;j++)    if(c[s1[i]]&&c[s1[i]]==disc[s2[j]]||(d[s2[j]]&&d[s2[j]]==disd[s1[i]]))    map[s1[i]][s2[j]]=true;    for(int i=1;i<=k;i++)    {        memset(road,0,sizeof(road));        if(find(i))ans++;    }    cout<<k-ans;}