最大点独立集

Sample Input
1 1 2
C1 D1
D1 C1


1 2 4
C1 D1
C1 D1
C1 D2
D2 C1
 
Sample Output
1
3


题意: 有n只毛,m只狗,p个孩子,每个孩子有喜欢的也有喜欢的动物,喜欢猫就不喜欢狗,反之亦然;
把孩子喜欢的留着,不喜欢的搬走,则孩子会高兴;问怎样搬动物,最大能让多少孩子高兴;
输入,第一个为喜欢,第二个为不喜欢;


思路: 把孩子看成一个点,a喜欢的b不喜欢,则ab矛盾,连一条边;则得到一个图;我们的目标是在这个图中找到
一个最大点独立集,即这个集合中的孩子任意两个都不矛盾,也就是可以同时高兴;
就简化为,建图, 最大点独立集 = 顶点数 - 匹配数 ; 求二分匹配 !!


#include<cstdio>
#include<cstring>
#include<map>
#include<vector>
#include<cmath>
#include<cstdlib>
#include<stack>
#include<queue>
#include <iomanip>
#include<iostream>
#include<algorithm>
using namespace std ;
const int N=2000 ;
int match[N];
bool vist[N];
char  yes[N][5],no[N][5];
vector<int>E[N];


int dfs(int u)
{
     for(int i = 0 ; i < E[u].size() ; i++) 
     {
      int  v=E[u][i];
      if(!vist[v])
      {
      vist[v]=true;
      if(match[v]==-1 || dfs(match[v]))
      {
        match[v]=u;
        return 1 ;
      }
      }
     }
  return 0;



int main()
{
int n,m,p;
while(~scanf("%d%d%d",&n,&m,&p))
{
for(int i=0;i<N;i++)
     E[i].clear();
for(int i = 0 ; i < p ; i++)
scanf("%s%s",yes[i],no[i]);  //喜欢的,不喜欢的
for(int i = 0 ; i < p ; i++)
 for(int j = i+1 ; j < p ; j++)
if(strcmp(yes[i],no[j])==0 || strcmp(yes[j],no[i])==0)  
   {                           //矛盾的孩子建边
      E[i].push_back(j);
      E[j].push_back(i);
   }
  int ans = 0 ;  
  memset(match,-1,sizeof(match));
  for(int i = 0 ; i < p ; i++)  
  {
     memset(vist,false,sizeof(vist));
     ans += dfs(i) ;        //求匹配
  }
 //printf("%d**",ans); 
 printf("%d\n",p-ans/2); //因为建的是双向边(相当于拆点),所以匹配数除以2
}
 return 0;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值