题意:n只猫,m只狗,p个人。每个人有一个喜欢的动物和一个不喜欢的动物,喜欢的动物和不喜欢的动物不是一种动物。现要移除一些动物。若自己喜欢的动物没有被移除且不喜欢的动物被移除,那么自己会很高兴。问最多能让几个人高兴。
题解:最大独立集
1.这个题以人建图,矛盾的人连无向边。a喜欢的动物与b不喜欢的动物相同称为矛盾。
2.套用匈牙利算法求最大匹配数,代入公式:最大独立集 = n - 最大匹配数。
#include<stdio.h>
#include<string.h>
#include<stdio.h>
#include<math.h>
#include<algorithm>
#include<queue>
#include<vector>
#define MAXN 505
#define inf 0x3f3f3f3f
using namespace std ;
int n , m , p ;
bool vis[MAXN] ;
int used[MAXN] ;
vector <int> edge[MAXN] ;
char like[MAXN][15] ;
char dislike[MAXN][15] ;
bool find(int u)
{
int i , j ;
int v ;
for(i = 0 ; i < edge[u].size() ; i ++)
{
v = edge[u][i] ;
if(!vis[v])
{
vis[v] = 1 ;
if(used[v] == -1 || find(used[v]))
//find(used[v])的参数used[v]将点v和点used[v]分为了两部分
{
used[v] = u ;
return 1 ;
}
}
}
return 0 ;
}
int Match()
{
int i , j ;
int ans = 0 ;
memset(used , -1 , sizeof(used)) ;
for(i = 1 ; i <= p ; i ++)
{
memset(vis , 0 , sizeof(vis)) ;
if(find(i))
ans ++ ;
}
return ans ;
}
int main()
{
int i , j , k ;
int u , v ;
int ans ;
while(scanf("%d%d%d" , &n , &m , &p) != EOF)
{
for(i = 1 ; i <= p ; i ++)
scanf("%s%s" , like[i] , dislike[i]) ;
for(i = 1 ; i <= p ; i ++)
edge[i].clear() ;
for(i = 1 ; i <= p ; i ++)
for(j = i + 1 ; j <= p ; j ++)
if(strcmp(like[i] , dislike[j]) == 0 || strcmp(dislike[i] , like[j]) == 0)
{
edge[i].push_back(j) ;
edge[j].push_back(i) ;
}
ans = Match() ;
printf("%d\n" , p - ans / 2) ;//无向图匹配最后除2
}
}