二分匹配之最大权值匹配算法---KM模板

百科:http://baike.baidu.com/link?url=vbM3H4XmfrsWfP-epdlR2sVKSNzOq4hXnWDqm5uo8fd7VWsF2SmhDV35XyVUDvVjvrtf42RUITJuNCHn-7_x6K

大神总结:http://www.cnblogs.com/skyming/archive/2012/02/18/2356919.html

代码:

 1 #include<stdio.h>
 2 #include<string.h>
 3 const int N=555,INF=0x3f3f3f3f;
 4 int lx[N],ly[N],vx[N],vy[N],slack[N],match[N];
 5 int a[N][N];
 6 int nx,ny;
 7 int dfs(int u)
 8 {
 9     vx[u]=1;
10     for(int i=1;i<=ny;i++)
11     {
12         if(vy[i])    continue;
13         int t=lx[u]+ly[i]-a[u][i];
14         if(t==0)
15         {
16             vy[i]=1;
17             if(match[i]==-1||dfs(match[i]))
18             {
19                 match[i]=u;
20                 return 1;
21             }
22         }
23         else if(slack[i]>t)
24             slack[i]=t;
25     }
26     return 0;
27 }
28 int KM()
29 {
30     int i,j,d;
31     memset(ly,0,sizeof(ly));
32     memset(match,-1,sizeof(match));
33     for(i=1,lx[i]=-INF;i<=nx;i++)
34         for(j=1;j<=ny;j++)
35             if(a[i][j]>lx[i])
36                 lx[i]=a[i][j];
37     for(i=1;i<=nx;i++)
38     {
39         memset(slack,0x3f,sizeof(slack));
40         while(1)
41         {
42             memset(vx,0,sizeof(vx));
43             memset(vy,0,sizeof(vy));
44             if(dfs(i))    break;
45             d=INF;
46             for(j=1;j<=ny;j++)
47                 if(!vy[j]&&slack[j]<d)
48                     d=slack[j];
49             //if(d==INF)    break;//该点找不到任何匹配
50             for(j=1;j<=nx;j++)
51                 if(vx[j])
52                     lx[j]-=d;
53             for(j=1;j<=ny;j++)
54             {
55                 if(vy[j])
56                     ly[j]+=d;
57                 else
58                     slack[j]-=d;
59             }
60         }
61     }
62     int ans=0,sum=0;
63     for(i=1;i<=ny;i++)
64         if(match[i]>-1&&a[match[i]][i])
65             ans+=a[match[i]][i],sum++;
66     printf("%d++\n",sum);//匹配数
67     return ans;
68 }
69 int main()
70 {
71     int m,u,v,w,n,i;
72     scanf("%d",&nx);
73     scanf("%d",&ny);
74     scanf("%d",&m);
75     memset(a,0,sizeof(a));
76     while(m--)
77     {
78         scanf("%d%d%d",&u,&v,&w);
79         a[u][v]=a[v][u]=w;
80     }
81     printf("%d\n",KM());
82     return 0;
83 }
时间: 2024-12-17 16:51:03

二分匹配之最大权值匹配算法---KM模板的相关文章

HDU2255-奔小康赚大钱-二分图最大权值匹配-KM算法

二分图最大权值匹配问题.用KM算法. 最小权值的时候把权值设置成相反数 1 /*--------------------------------------------------------------------------------------*/ 2 3 #include <algorithm> 4 #include <iostream> 5 #include <cstring> 6 #include <ctype.h> 7 #include &l

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

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

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

最大权二分匹配

图论里有一个非常经典的算法,那就是二分匹配,只是仅仅是简单的匹配有时并不能解决我们的问题,比方匹配带权的情况.引申的一个非常重要的问题就是分配问题,比方给n个人分派m个任务,每一个人都有不同的成本,怎样分配能使得成本最小就是这种问题,这种问题我们统称为二分图的最大权匹配问题. 解决这类问题的最好的方法应该就是KM 算法.详细细节能够自己百度! 以下是我的代码,我主要还是用了类来写,认为这样比較好理解! #include<iostream> #include<cstdio> #inc

hdu 1853 Cyclic Tour 最大权值匹配 全部点连成环的最小边权和

链接:http://acm.hdu.edu.cn/showproblem.php?pid=1853 Cyclic Tour Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/65535 K (Java/Others) Total Submission(s): 1904    Accepted Submission(s): 951 Problem Description There are N cities in our c

hdu 1853 Cyclic Tour 最大权值匹配 所有点连成环的最小边权和

链接:http://acm.hdu.edu.cn/showproblem.php?pid=1853 Cyclic Tour Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/65535 K (Java/Others) Total Submission(s): 1904    Accepted Submission(s): 951 Problem Description There are N cities in our c

poj3565 Ants km算法求最小权完美匹配,浮点权值

/** 题目:poj3565 Ants km算法求最小权完美匹配,浮点权值. 链接:http://poj.org/problem?id=3565 题意:给定n个白点的二维坐标,n个黑点的二维坐标. 求是否存在n条边,每条边恰好连一个白点,一个黑点,且所有的边不相交. 输出所有黑点连接的白点编号. 思路:最小权完美匹配. 假定有白点1(a1,b1), 2(a2,b2), 黑点3(a3,b3),4(a4,b4); 如果1(a1,b1)与3(a3,b3)相连,2(a2,b2)与4(a4,b4)相连,如

二分匹配

PS:二分图匹配这一章的内容,我认为最重要的是要弄清楚概念. 一些定义: 二分图:二分图又称作二部图,是图论中的一种特殊模型. 设G=(V,E)是一个无向图,如 果顶点V可分割为两个互不相交的子集(A,B),并且图中的每条边(i,j)所关联 的两个顶点i和j分别属于这两个不同的顶点集(i in A,j in B),则称图G为一个 二分图.记为G=(A,B;E). 二分图匹配:给定一个二分图G,M为G边集的一个子集,如果M满足当中的任意两条边都不依附于同一个顶点,则称M是一个匹配. 需要强调的是:

poj1274 二分匹配

今天复习二分匹配,A 了一道模板题. 二分匹配需要理解增广路的寻找.用dfs来更新最大匹配.注意一些点:赋初值:愚蠢地把==写成了= ; 然后match的记值;每个点都要重新走一遍. 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #define INF 80005 6 #define maxn 405 7 using namespace