题目大意:
有一些猫和狗,和一些人,每个人有一个喜欢的动物和不喜欢的动物(它们一定是一只猫和一只狗或一只狗和一只猫)。现在要移走一些动物,如果一个人喜欢的动物没有被移走,但不喜欢的被移走了,那么他就很高兴。问最多能让多少人高兴。
解题思路:
题面非常强烈的诱导我们把猫狗作为结点,把人作为边,但是这样就成了一个点带权的最大独立集,无法求解。这时我们就要考虑把点和边交换。把人作为点,如果两个人的爱好有冲突就在他们之间连边,这样建图最大独立集就是答案。
AC代码:
#include <iostream> #include <algorithm> #include <cstdio> #include <cstring> #include <cstdlib> #include <cmath> #include <ctime> #include <vector> #include <queue> #include <stack> #include <deque> #include <string> #include <map> using namespace std; #define INF 0x3f3f3f3f #define LL long long #define fi first #define se second #define mem(a,b) memset((a),(b),sizeof(a)) const int MAXV=500+3; pair<string,string> like[MAXV];//每个人喜欢和不喜欢的动物 int N,M,P; vector<int> G[MAXV]; int match[MAXV]; bool used[MAXV]; void init() { for(int i=0;i<P;++i) G[i].clear(); } bool dfs(int v) { used[v]=true; for(int i=0;i<G[v].size();++i) { int u=G[v][i],w=match[u]; if(w<0||!used[w]&&dfs(w)) { match[v]=u; match[u]=v; return true; } } return false; } int bipartite_matching()//匈牙利算法求最大匹配 { int res=0; mem(match,-1); for(int v=0;v<P;++v) { if(match[v]<0) { mem(used,0); if(dfs(v)) ++res; } } return res; } int main() { cin.sync_with_stdio(false); while(cin>>N>>M>>P) { init(); for(int i=0;i<P;++i) cin>>like[i].fi>>like[i].se; for(int i=0;i<P;++i) for(int j=i+1;j<P;++j) if(like[i].fi==like[j].se||like[i].se==like[j].fi) { G[i].push_back(j); G[j].push_back(i); } cout<<P-bipartite_matching()<<'\n'; } return 0; }