HDU1068 二分匹配

来源:互联网 发布:金山打字软件 编辑:程序博客网 时间:2024/05/17 08:29

3个重要结论:

最小点覆盖数: 最小覆盖要求用最少的点(X集合或Y集合的都行)让每条边都至少和其中一个点关联。可以证明:最少的点(即覆盖数)=最大匹配数
最小路径覆盖=最小路径覆盖=|N|-最大匹配数
用尽量少的不相交简单路径覆盖有向无环图G的所有结点。解决此类问题可以建立一个二分图模型。把所有顶点i拆成两个:X结点集中的i和Y结点集中的i',如果有边i->j,则在二分图中引入边i->j',设二分图最大匹配为m,则结果就是n-m。
二分图最大独立集=顶点数-二分图最大匹配
在N个点的图G中选出m个点,使这m个点两两之间没有边,求m最大值。
如果图G满足二分图条件,则可以用二分图匹配来做.最大独立集点数 = N - 最大匹配数。


这里就是第三个结论,二分图最大独立集=顶点数-二分图最大匹配

题目大意:给你每个人互相认识的人,然后问最多能找到多少个人都互不认识。其实就是找:最大独立集合


#include<iostream>#include<cstdio>#include<list>#include<algorithm>#include<cstring>#include<string>#include<queue>#include<stack>#include<map>#include<vector>#include<cmath>#include<memory.h>#include<set>#define ll long long#define LL __int64#define eps 1e-8const ll INF=9999999999999;using namespace std;#define M 400000100#define inf 0xfffffff//vector<pair<int,int> > G;//typedef pair<int,int> P;//vector<pair<int,int>> ::iterator iter;////map<ll,int>mp;//map<ll,int>::iterator p;vector<int>G[1012];int marry[1012];bool vis[1012];void clear(){memset(marry,-1,sizeof(marry));for(int i=0;i<1012;i++)G[i].clear();}bool dfs(int x){for(int i=0;i<G[x].size();i++){int v=G[x][i];if(!vis[v]){vis[v]=true;if(marry[v]==-1 || dfs(marry[v])){marry[v]=x;return 1;}}}return 0;}int main(void){int n;while(~scanf("%d",&n)){clear();int number,num,a;for(int i=0;i<n;i++){scanf("%d: (%d) ",&number,&num);for(int j=0;j<num;j++){scanf("%d",&a);G[number].push_back(a);}}int ans=0;for(int i=0;i<n;i++){memset(vis,false,sizeof(vis));if(dfs(i))ans++;}printf("%d\n",n-ans/2);}}



原创粉丝点击