俗称HK算法。和匈牙利算法一个功能,但是复杂度更优。匈牙利算法复杂度O(VE),HK算法复杂度O(sqrt(V)*E)。
但是很容易写崩,别问我怎么知道的。
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int MAXN=500;// 最大点数 4 const int INF=1<<28;// 距离初始值 5 int bmap[MAXN][MAXN];//二分图 6 int cx[MAXN];//cx[i]表示左集合i顶点所匹配的右集合的顶点序号 7 int cy[MAXN]; //cy[i]表示右集合i顶点所匹配的左集合的顶点序号 8 int nx,ny; 9 int dx[MAXN]; 10 int dy[MAXN]; 11 /*dx[i]表示左集合i顶点的距离编号,dy[i]表示右集合i顶点的距离编号*/ 12 int dis; 13 bool bmask[MAXN]; 14 //寻找 增广路径集 15 bool searchpath() 16 { 17 queue<int>Q; 18 dis=INF; 19 memset(dx,-1,sizeof(dx));//第几层 20 memset(dy,-1,sizeof(dy)); 21 for(int i=1;i<=nx;i++) 22 { 23 //cx[i]表示左集合i顶点所匹配的右集合的顶点序号 24 if(cx[i]==-1) 25 { 26 //将未遍历的节点 入队 并初始化次节点距离为0 27 Q.push(i); 28 dx[i]=0;//第0层 29 } 30 } 31 //广度搜索增广路径 32 while(!Q.empty()) 33 { 34 int u=Q.front(); 35 Q.pop(); 36 if(dx[u]>dis) break; 37 //取右侧节点 38 for(int v=1;v<=ny;v++) 39 { 40 //右侧节点的增广路径的距离 41 if(bmap[u][v]&&dy[v]==-1) 42 { 43 dy[v]=dx[u]+1; //v对应的距离 为u对应距离加1 44 if(cy[v]==-1) dis=dy[v]; //如果该点未被匹配,那么增广路形成 45 else //如果该点匹配了,那么接着往下搜 46 { 47 dx[cy[v]]=dy[v]+1; 48 Q.push(cy[v]); 49 } 50 } 51 } 52 } 53 return dis!=INF; 54 } 55 //寻找路径 深度搜索 56 int findpath(int u) 57 { 58 for(int v=1;v<=ny;v++) 59 { 60 //如果该点没有被遍历过 并且距离为上一节点+1 61 if(!bmask[v]&&bmap[u][v]&&dy[v]==dx[u]+1) 62 { 63 //对该点染色 64 bmask[v]=1; 65 if(cy[v]!=-1&&dy[v]==dis) //如果该点已经被匹配了并且为最后一个匹配点,那么这条路径不是增广路。即是说这条路的结点已经匹配 66 { 67 continue; 68 } 69 if(cy[v]==-1||findpath(cy[v])) //如果该点未匹配或者后面的点能腾出位置,那么这就是增广路 70 { 71 cy[v]=u;cx[u]=v; 72 return 1; 73 } 74 } 75 } 76 return 0; 77 } 78 //得到最大匹配的数目 79 int MaxMatch() 80 { 81 int res=0; 82 memset(cx,-1,sizeof(cx)); 83 memset(cy,-1,sizeof(cy));//cx[i]表示左集合i顶点所匹配的右集合的顶点序号 84 while(searchpath()) //如果存在增广路 一直迭代到无增广路 85 { 86 memset(bmask,0,sizeof(bmask));//标记数组 87 for(int i=1;i<=nx;i++) 88 { 89 if(cx[i]==-1) 90 { 91 res+=findpath(i); 92 } 93 } 94 } 95 return res; 96 } 97 int main() 98 { 99 int num; 100 scanf("%d",&num); 101 while(num--) 102 { 103 memset(bmap,0,sizeof(bmap)); 104 scanf("%d%d",&nx,&ny); 105 for(int i=1;i<=nx;i++) 106 { 107 int snum; 108 scanf("%d",&snum); 109 int u; 110 for(int j=1;j<=snum;j++) 111 { 112 scanf("%d",&u); 113 bmap[i][u]=1; 114 // bmap[u][i]=1; 115 } 116 } 117 // cout<<MaxMatch()<<endl; 118 if(MaxMatch()==nx) 119 { 120 printf("YES "); 121 } 122 else 123 { 124 printf("NO "); 125 } 126 } 127 //system("pause"); 128 return 0; 129 }