hdu 1068 Girls and Boys

来源:互联网 发布:用户画像的数据来源 编辑:程序博客网 时间:2024/05/20 21:43

这道题和hdu 1054同样是二分图匹配相关的问题。
二分图
最大匹配数=最小点覆盖数。

DAG 最小路径覆盖=顶点数-最大匹配数

最大独立集=顶点数-最大匹配数。

当一个图是无向图时,需要从每一个顶点进行最大匹配查找,所以无向图的最大匹配数是求出的最大匹配数/2;
或者可以理解为: 当图是无向图时, 左边的集合是包含了所有的顶点, 是有向图时,只包含了一部分顶点。

匈牙利算法:

 vector<int> left_set; vecto<int> adj[n];// n is the node num// adj is a array or vector is the set of adj node of v;bool dfs(int v){    for(int i=0;i<adj[v].size();i++){        if(!visited[adj[v][i]])        {            visited[adj[v][i]]=true;            if(match[adj[v][i]]==-1||dfs(match[adj[v][i]]){                match[adj[v][i]]=v;                return true;            }        }    }}int hungarian(){    int num=0;    for(int i=0;i<left_set.size();i++){  // 对于无向图 left_set 是整个集合        memset(visited,false,sizeof(visited));        if(dfs(left_set[i]) num++;    }}

另外对于多组输入数据,记得每处理一组数据后,把一些变量重新设为初始状态,比如,清空vector
重置状态数组为初始状态等。

下面是代码:

#include <iostream>#include<cstdio>#include<vector>#include<cstring>using namespace std;#define MAX 100000vector<int> stu[MAX];int match[MAX];bool visited[MAX];int n;bool  dfs(int i){    for(int j=0;j<stu[i].size();j++){        int tmp=stu[i][j];        //not have visited        if(!visited[tmp]){            visited[tmp]=true;            if(match[tmp]==-1||dfs(match[tmp])){                match[tmp]=i;                return true;            }        }    }    return false;}int hungarian(){    memset(match,-1,sizeof(match));    int num=0;    for(int i=0;i<n;i++){        memset(visited,false,sizeof(visited));        if(dfs(i)) num++;    }    return num;}int main(){    while(scanf("%d",&n)!=EOF){        int id,r; // id and the num        for(int i=0;i<n;i++) stu[i].clear();        for(int i=0;i<n;i++){            scanf("%d: (%d)",&id,&r);            for(int j=0;j<r;j++){                int tmp;                cin>>tmp;                stu[id].push_back(tmp);            }        }        int matchNum=hungarian()/2;        int result=0;        result=n-matchNum;        cout<<result<<endl;    }    return 0;}