题意
有G个女孩和B个男孩,男生互相认识,女生也互相认识,有M对男生认识女生,现要选出最多的人并且互相认识。
1 ≤ G, B ≤ 200,0 ≤ M ≤ G × B
题解
但是我们发现,男孩之间都互相认识,女孩之间也互相认识,这样不能划分点集的。 但是男孩之间都互相认识,女孩之间也互相认识,所以男孩和男孩,女孩和女孩之间不存在不认识关系 如果以不认识作为边的话,认识不连边,这样就能划开点集。
那么我们求最大独立集(任意两点之间没有连边)即可。
最大独立集=点数-最大匹配数
#include<cstdio> #include<vector> #include<cstring> using namespace std; const int maxn=405; int n,m,q,timer; int match[maxn],vis[maxn]; bool connect[maxn][maxn]; vector<int> e[maxn]; void init(){ memset(match,0,sizeof(match)); memset(vis,0,sizeof(vis)); memset(connect,false,sizeof(connect)); for(int i=1;i<=n;i++) e[i].clear(); timer=0; } bool dfs(int u){ if(vis[u]==timer) return false; vis[u]=timer; for(unsigned int i=0;i<e[u].size();i++){ int v=e[u][i]; if(!match[v]||dfs(match[v])){ match[v]=u; return true; } } return false; } int main(){ int tot=0; while(tot++,scanf("%d%d%d",&n,&m,&q),n){ init(); for(int i=1;i<=q;i++){ int x,y; scanf("%d%d",&x,&y); y+=n; connect[x][y]=true; } for(int i=1;i<=n;i++) for(int j=n+1;j<=n+m;j++) if(!connect[i][j]) e[i].push_back(j); int ans=0; for(int i=1;i<=n;i++){ timer++; if(dfs(i)) ans++; } printf("Case %d: %d ",tot,n+m-ans); } }