匈牙利算法模板:
#include<bits/stdc++.h> #define MAXN 9999 using namespace std; int nx,ny;//nx表示二分图左边顶点的个数,ny表示二分图右边顶点的个数 int m;//m代表边的条数 int cx[MAXN],cy[MAXN];//如果有cx[i]=j,则必有cy[j]=i,说明i点和j点能够匹配 int x,y;//x点到y点有边 int e[MAXN][MAXN];//邻接矩阵 int visited[MAXN];//标记数组,标记的永远是二分图右边的顶点 int ret;//最后结果 int point(int u)//这个函数的作用是寻找增广路和更新cx,xy数组,如果找到了增广路,函数返回1,找不到,函数返回0。 { for(int v=1;v<=ny;v++)//依次遍历右边的所有顶点 { if(e[u][v]&&!visited[v])//条件一:左边的u顶点和右边的v顶点有连通边, //条件二:右边的v顶点在没有被访问过,这两个条件必须同时满足 { visited[v]=1;//将v顶点标记为访问过的 if(cy[v]==-1||point(cy[v]))//条件一:右边的v顶点没有左边对应的匹配的点, {//条件二:以v顶点在左边的匹配点为起点能够找到一条增广路(如果能够到达条件二,说明v顶点在左边一定有对应的匹配点)。 cx[u]=v;//更新cx,cy数组 cy[v]=u; return 1; } } } return 0;//如果程序到达了这里,说明对右边所有的顶点都访问完了,没有满足条件的。 } int main() { while (cin>>m>>nx>>ny) { memset(cx,-1,sizeof(cx));//初始化cx,cy数组的值为-1 memset(cy,-1,sizeof(cy)); memset(e,0,sizeof(e));//初始化邻接矩阵 ret=0; while (m--)//输入边的信息和更新邻接矩阵 { cin>>x>>y; e[x][y]=1; } for(int i=1;i<=nx;i++)//对二分图左边的所有顶点进行遍历 { if(cx[i]==-1)//如果左边的i顶点还没有匹配的点,就对i顶点进行匹配 { memset(visited,0,sizeof(visited));//每次进行point时,都要对visited数组进行初始化 ret+=point(i);//point函数传入的参数永远是二分图左边的点 } } cout<<ret<<endl; } }
例题:hdu 1083
代码:
#include<iostream> #include<iostream> #include<stdio.h> #include<string.h> using namespace std; const int max_n=105,max_m=305; bool edge[max_n][max_m],vis[max_m]; int cx[max_n],cy[max_m]; int n,m; int pointn(int u) { for(int v=1;v<=m;v++) { if(edge[u][v]==1&&vis[v]==0) { vis[v]=1; if(cy[v]==-1||pointn(cy[v])) { cx[u]=v; cy[v]=u; return 1; } } } return 0; } int main() { int t; scanf("%d",&t); while(t--) { int res=0; //cout<<res<<endl; memset(cx,-1,sizeof(cx)); memset(cy,-1,sizeof(cy)); memset(edge,0,sizeof(edge)); scanf("%d %d",&n,&m); for(int i=1;i<=n;i++) { int k; scanf("%d",&k); for(int j=0;j<k;j++) { int x; scanf("%d",&x); edge[i][x]=1; } } for(int i=1;i<=n;i++) { if(cx[i]==-1) { memset(vis,0,sizeof(vis)); res+=pointn(i); } // cout<<res<<endl; } if(res==n) printf("YES "); else printf("NO "); } return 0; }