最大权二分匹配

图论里有一个非常经典的算法,那就是二分匹配,只是仅仅是简单的匹配有时并不能解决我们的问题,比方匹配带权的情况。引申的一个非常重要的问题就是分配问题,比方给n个人分派m个任务,每一个人都有不同的成本,怎样分配能使得成本最小就是这种问题,这种问题我们统称为二分图的最大权匹配问题.

解决这类问题的最好的方法应该就是KM 算法。详细细节能够自己百度!

以下是我的代码,我主要还是用了类来写,认为这样比較好理解!

#include<iostream>
#include<cstdio>
#include<vector>
using namespace std;
#define INF 99999999
class graph{
  struct vertex
  {
	 bool vist;              //是否被訪问过
     int link;              //顶标
     int ver;               //匹配边
	 vector<int>edge;      //相关边
	 vertex(bool f=0,int v=0,int l=-INF):vist(f),ver(v),link(l){}
  };
  int n,m;
  vector<vertex>V;
  vector<vertex>U;
  vector<int>slack;
  public:
	  graph(int x,int y):n(x),m(y)
	  {
		  vertex tmp;
		  int i=0;
		  for(;i<=n;i++)
		  V.push_back(tmp),
		  V[i].edge.push_back(0);
		  for(i=0;i<=m;i++)
			  U.push_back(tmp),
			  slack.push_back(INF);
	  }
	  void merge(int i,int w)
	  {
		  V[i].edge.push_back(w);
		  V[i].link=V[i].link>w?V[i].link:w;
	  }
      bool DFS(int x)
	  {
		  V[x].vist=1;
		  for(int y=1;y<=m;y++)
		  {
             if(U[y].vist)
				 continue;
			 int tmp=V[x].link+U[y].link-V[x].edge[y];
			 if(tmp==0)
			 {
				 U[y].vist=1;
				 if(U[y].ver==0||DFS(U[y].ver))
				 {
					 U[y].ver=x;
					 V[x].ver=y;
					 return 1;
				 }
			 }
			 else if(slack[y]>tmp)
				 slack[y]=tmp;
		  }
		  return 0;
	  }
    int KM()
	{
		for(int x=1;x<=n;x++)
		{
		   for(int i=1;i<=m;i++)
		    slack[i]=INF;
         while(1)
		 {
		   for(int i=1;i<=n;i++)
		    V[i].vist=0;
		    for(int i=1;i<=m;i++)
		    U[i].vist=0;
		   if(DFS(x))
               break;
             int d=INF ;
            for(int i=1;i<=m;i++)
				if(!U[i].vist&&d>slack[i])
					d=slack[i];
			for(int j=1;j<=n;j++)
				if(V[j].vist)
					V[j].link-=d;
			for(int k=1;k<=m;k++)
				if(U[k].vist)
					U[k].link+=d;
				else
					slack[k]-=d;
		 }
       }
    	int MAX=0;
    	for(int i=1;i<=m;i++)
	    {
	       if(V[i].ver>0)
            MAX+=V[U[i].ver].edge[i];

        }
		return MAX;
	}

  };

int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
	int n,m;
	while(cin>>n>>m)
	{
	  graph G(n,n);
	  int w;
	  for(int i=1;i<=n;i++)
		  for(int j=1;j<=n;j++)
			 scanf("%d",&w),
			 G.merge(i,-w);
	  int max=-G.KM();
          cout<<max<<endl;

	}
	  //  fclose(stdin);
	//    fclose(stdout);
	return 0;
}

这个算法的效率是O(n^3)的,这应该是眼下最好的算法了吧。

时间: 2024-08-08 22:10:05

最大权二分匹配的相关文章

kuangbin带你飞 匹配问题 二分匹配 + 二分图多重匹配 + 二分图最大权匹配 + 一般图匹配带花树

二分匹配:二分图的一些性质 二分图又称作二部图,是图论中的一种特殊模型. 设G=(V,E)是一个无向图,如果顶点V可分割为两个互不相交的子集(A,B),并且图中的每条边(i,j)所关联的两个顶点i和j分别属于这两个不同的顶点集(i in A,j in B),则称图G为一个二分图. 1.一个二分图中的最大匹配数等于这个图中的最小点覆盖数 König定理是一个二分图中很重要的定理,它的意思是,一个二分图中的最大匹配数等于这个图中的最小点覆盖数.如果你还不知道什么是最小点覆盖,我也在这里说一下:假如选

【二分图最大权完美匹配】【KM算法模板】【转】

[文章详解出处]https://www.cnblogs.com/wenruo/p/5264235.html KM算法是用来求二分图最大权完美匹配的.[也就算之前的匈牙利算法求二分最大匹配的变种??] 这里就贴一下模板代码..2333... 1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <algorithm> 5 using namespace std; 6

Tour HDU - 3488(最大权值匹配)

Tour In the kingdom of Henryy, there are N (2 <= N <= 200) cities, with M (M <= 30000) one-way roads connecting them. You are lucky enough to have a chance to have a tour in the kingdom. The route should be designed as: The route should contain o

HDU 3861 The King’s Problem (强连通+二分匹配)

题目地址:HDU 3861 这题虽然是两个算法结合起来的.但是感觉挺没意思的..结合的一点也不自然,,硬生生的揉在了一块...(出题者不要喷我QAQ.) 不过这题让我发现了我的二分匹配已经好长时间没用过了..都快忘了..正好在省赛之前又复习了一下. 代码如下: #include <iostream> #include <string.h> #include <math.h> #include <queue> #include <algorithm>

hdu 4185 Oil Skimming(二分匹配)

Oil Skimming Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 883    Accepted Submission(s): 374 Problem Description Thanks to a certain "green" resources company, there is a new profitable

【DFS求树的最大二分匹配+输入外挂】HDU 6178 Monkeys

http://acm.hdu.edu.cn/showproblem.php?pid=6178 [题意] 给定一棵有n个结点的树,现在有k个猴子分布在k个结点上,我们可以删去树上的一些边,使得k个猴子每个猴子都至少和其他一个猴子相连 问树上最少保留多少条边 [思路] 每个猴子要至少和一个猴子相连,考虑保留的边最少,那么最优的情况一定是一条边的两个顶点放两个猴子,这些边的顶点都不重合 我们现在要找到给定的树中最多有多少条这样的边,即最大二分匹配 O(n)的DFS,对于每个结点,优先与叶子结点形成一条

hdu 5093 Battle ships 最大二分匹配

Battle ships Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 589    Accepted Submission(s): 233 Problem Description Dear contestant, now you are an excellent navy commander, who is responsible

二分匹配最大匹配 PKU1469

一个学生可以有多种选择,问能否每个学生刚好选一门课,但是每门课最多只有一个学生可以选择 典型的二分匹配最大匹配,直接套模板 COURSES Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 17878   Accepted: 7048 Description Consider a group of N students and P courses. Each student visits zero, one or more

hdoj 2063 过山车 【二分匹配之匈牙利算法】

过山车 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 11520    Accepted Submission(s): 5072 Problem Description RPG girls今天和大家一起去游乐场玩,终于可以坐上梦寐以求的过山车了.可是,过山车的每一排只有两个座位,而且还有条不成文的规矩,就是每个女生必须找个个男生做pa