二分图匹配

来源:互联网 发布:联合国维和行动 知乎 编辑:程序博客网 时间:2024/05/21 03:55

(1)一个二分图中的最大匹配数等于这个图中的最小点覆盖数
(2)最小路径覆盖=|G|-最大匹配数
(3)二分图最大独立集=顶点数-二分图最大匹配

邻接矩阵:

///二分图匹配(匈牙利算法的DFS实现)(邻接矩阵形式)///初始化:g[][]两边的顶点划分情况///建立g[i][j]表示i->j的有向边,是左边向右边的匹配///g没有边相连则初始化为0///uN是匹配左边的顶点数,vN是匹配右边的顶点数///调用:res=hungary();输出最大匹配数///优点:适用于稠密图,dfs找增广路,实现简洁易于理解///时间复杂度:O(VE)#include<iostream>#include<cstdio>#include<string>#include<cmath>#include<vector>#include<map>#include<set>#include<queue>#include<algorithm>#include<cstring>using namespace std;const int INF=0x3f3f3f3f;const int MAXN=505;//顶点编号从0开始int uN,vN;//u,v的数目,使用前必须赋值int g[MAXN][MAXN];//邻接矩阵int linker[MAXN];bool used[MAXN];bool dfs(int u){  for(int v=0;v<vN;v++)  {    if(g[u][v]&&!used[v])    {      used[v]=true;      //没有匹配过或者能找到增广路      if(linker[v]==-1||dfs(linker[v]))      {        linker[v]=u;        return true;      }    }  }  return false;}int hungary(){  int res=0;  memset(linker,-1,sizeof(linker));  for(int u=0;u<uN;u++)  {    memset(used,false,sizeof(used));    if(dfs(u)) res++;  }  return res;}int main(){    int T;  scanf("%d",&T );  while(T--)  {    memset(g,0,sizeof(g));    int p,n;    scanf("%d%d",&p,&n);    uN=p;vN=n;    int c,stu;    for(int i=0;i<p;i++)    {      scanf("%d",&c);      for(int j=0;j<c;j++)      {        scanf("%d",&stu );        stu--;        g[i][stu]=1;      }    }    int res=hungary();    if(res==p) printf("YES\n");    else printf("NO\n");  }    return 0;}/*23 33 1 2 32 1 21 13 32 1 32 1 31 1*/

邻接表:

///匈牙利算法的邻接表形式///使用前用init()进行初始化,给uN赋值///加边使用函数addedge(u,v)#include<iostream>#include<cstdio>#include<string>#include<cmath>#include<vector>#include<map>#include<set>#include<queue>#include<algorithm>#include<cstring>using namespace std;const int INF=0x3f3f3f3f;const int MAXN=5e3+5;//点数的最大值const int MAXM=5e4+5;//边数的最大值struct Edge{  int to,nxt;}edge[MAXM];int head[MAXN],tot;void init(){  tot=0;  memset(head,-1,sizeof(head));}void addedge(int u,int v){  edge[tot].to=v;  edge[tot].nxt=head[u];  head[u]=tot++;}int linker[MAXN];bool used[MAXN];int uN;bool dfs(int u){  for(int i=head[u];i!=-1;i=edge[i].nxt)  {    int v=edge[i].to;    if(!used[v])    {      used[v]=true;      if(linker[v]==-1||dfs(linker[v]))      {        linker[v]=u;        return true;      }    }  }  return false;}int hungary(){  int res=0;  memset(linker,-1,sizeof(linker));  for(int u=0;u<uN;u++)//点的编号0~uN-1  {    memset(used,false,sizeof(used));    if(dfs(u)) res++;  }  return res;}int main(){    int T;  scanf("%d",&T );  while(T--)  {    init();    int p,n;    scanf("%d%d",&p,&n);    uN=p;    int c,stu;    for(int i=0;i<p;i++)    {      scanf("%d",&c);      for(int j=0;j<c;j++)      {        scanf("%d",&stu );        stu--;        addedge(i,stu);      }    }    int res=hungary();    if(res==p) printf("YES\n");    else printf("NO\n");  }    return 0;}/*23 33 1 2 32 1 21 13 32 1 32 1 31 1*/
原创粉丝点击