在网上找了一份挺好的模板,先标一下哦~链接君:http://blog.csdn.net/abcjennifer/article/details/5844579

#include <iostream>
#include <string.h>
#include <algorithm>
#include <iostream>
using namespace std;
int max(int a,int b)
{return a<b?b:a;} int min(int a,int b)
{return a<b?a:b;} const int size = ;
const int INF = ; bool map[size][size]; // 二分图的相等子图, map[i][j] = true 代表Xi与Yj有边
bool sx[size], sy[size]; // 标记在一次DFS中,Xi与Yi是否在交错树上
int match[size]; // 保存匹配信息,其中i为Y中的顶点标号,match[i]为X中顶点标号 bool DFS(int, const int);
void KM_Perfect_Match(const int n, const int edge[][size])
{
int i, j;
int lx[size], ly[size]; // KM算法中Xi与Yi的标号
for(i = ; i < n; i++)
{
lx[i] = -INF;
ly[i] = ;
for(j = ; j < n; j++)
{
lx[i] = max(lx[i], edge[i][j]);
}
}
bool perfect = false;
while(!perfect)
{
// 初始化邻接矩阵
for(i = ; i < n; i++)
{
for(j = ; j < n; j++)
{
if(lx[i]+ly[j] == edge[i][j])
map[i][j] = true;
else map[i][j] = false;
}
}
// 匹配过程
int live = ;
memset(match, -, sizeof(match));
for(i = ; i < n; i++) {
memset(sx, false, sizeof(sx));
memset(sy, false, sizeof(sy));
if(DFS(i, n)) live++;
else {
sx[i] = true;
break;
}
}
if(live == n) perfect = true;
else {
// 修改标号过程
int ex = INF;
for(i = ; i < n; i++)
{
for(j = ; sx[i] && j < n; j++)
{
if(!sy[j])
ex = min(ex, lx[i]+ly[j]-edge[i][j]);
}
}
for(i = ; i < n; i++)
{
if(sx[i]) lx[i] -= ex;
if(sy[i]) ly[i] += ex;
}
}
}
} bool DFS(int p, const int n)//find augment path from X[p]
{
int i;
for(i = ; i < n; i++)
{
if(!sy[i] && map[p][i])
{
sy[i] = true;
int t = match[i];
match[i] = p;
if(t == - || DFS(t, n))
{
return true;
}
match[i] = t;
if(t != -) sx[t] = true;
}
}
return false;
} int main()
{
int n, edge[size][size]; // edge[i][j]为连接Xi与Yj的边的权值
int i;
int m;
/***************************************************
* record edge[i][j] as edge value between vertex i in X and vertex j in Y
* save n as vertexs need to be match (used in KM_Perfect_Match(n, edge);)
***************************************************/
int s,d,pow; while(scanf("%d%d",&n,&m)!=EOF)
{
if(n== && m==) break;
memset(edge,,sizeof(edge));
/*最小权: 去掉memset(edge,0,sizeof(edge));改为如下:
for(i=0;i<n;i++)
for(int j=0;j<n;j++)
edge[i][j]=-INF;
*/
memset(sx,,sizeof(sx));
memset(sy,,sizeof(sy));
memset(match,,sizeof());
while(m--)
{
scanf("%d%d%d",&s,&d,&pow);
s--;d--;
/*最小权:edge[s][d]=pow; 改为edge[s][d]= - pow;*/
edge[s][d]=pow;
}
KM_Perfect_Match(n, edge);
int cost = ;
for(i=;i<n;i++)
{
cost += edge[match[i]][i];
}
/*最小权:output 改为 -cost*/
cout<<cost<<endl;
}
// cost 为最大匹配的总和, match[]中保存匹配信息
return ;
}

感觉这个模板也不错,比较符合审美。。。

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm> using namespace std;
const int maxn = ;
const int inf = 0x3f3f3f3f; int N, L[maxn], Lx[maxn], Ly[maxn], W[maxn][maxn], slack[maxn];
bool S[maxn], T[maxn]; int match (int u) {
S[u] = true;
for (int i = ; i <= N; i++) if (!T[i]) {
if (Lx[u] + Ly[i] == W[u][i]) {
T[i] = true;
if (!L[i] || match(L[i])) {
L[i] = u;
return true;
}
} else
slack[i] = min(slack[i], Lx[u]+Ly[i]-W[u][i]);
}
return false;
} void update () {
int a = inf;
for (int i = ; i <= N; i++) if (!T[i])
a = min(a, slack[i]); for (int i = ; i <= N; i++) {
if (S[i]) Lx[i] -= a;
if (T[i]) Ly[i] += a;
}
} void KM () {
for (int i = ; i <= N; i++) {
L[i] = Lx[i] = Ly[i] = ;
for (int j = ; j <= N; j++)
Lx[i] = max(Lx[i], W[i][j]);
} for (int i = ; i <= N; i++) {
for (int j = ; j <= N; j++) slack[j] = inf;
while (true) {
for (int j = ; j <= N; j++) S[j] = T[j] = false;
if (match(i)) break;
else update();
}
}
} void init () {
for (int i = ; i <= N; i++)
for (int j = ; j <= N; j++)
W[i][j] = -inf;
int u, v;
for (int i = ; i <= N; i++) {
while (scanf("%d", &u) == && u) {
scanf("%d", &v);
W[i][u] = max(W[i][u], -v);
}
}
} int main () {
while (scanf("%d", &N) == && N) {
init();
KM();
bool flag = false;
for (int i = ; i <= N; i++) {
if (L[i] && W[L[i]][i] == -inf)
flag = true;
} if (flag) printf("N\n");
else {
int ans = ;
for (int i = ; i <= N; i++)
ans += (Lx[i] + Ly[i]);
printf("%d\n", -ans);
}
}
return ;
}

二分图最大权最小权完美匹配模板KM的更多相关文章

  1. UVA 1349 Optimal Bus Route Design (二分图最小权完美匹配)

    恰好属于一个圈,那等价与每个点有唯一的前驱和后继,这让人想到了二分图, 把一个点拆开,点的前驱作为S集和点的后继作为T集,然后连边,跑二分图最小权完美匹配. 写的费用流..最大权完美匹配KM算法没看懂 ...

  2. hdu1533 Going Home km算法解决最小权完美匹配

    Going Home Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total ...

  3. 紫书 例题11-10 UVa 1349 (二分图最小权完美匹配)

    二分图网络流做法 (1)最大基数匹配.源点到每一个X节点连一条容量为1的弧, 每一个Y节点连一条容量为1的弧, 然后每条有向 边连一条弧, 容量为1, 然后跑一遍最大流即可, 最大流即是最大匹配对数 ...

  4. UVa 1349 (二分图最小权完美匹配) Optimal Bus Route Design

    题意: 给出一个有向带权图,找到若干个圈,使得每个点恰好属于一个圈.而且这些圈所有边的权值之和最小. 分析: 每个点恰好属于一个有向圈 就等价于 每个点都有唯一后继. 所以把每个点i拆成两个点,Xi  ...

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

    /** 题目:poj3565 Ants km算法求最小权完美匹配,浮点权值. 链接:http://poj.org/problem?id=3565 题意:给定n个白点的二维坐标,n个黑点的二维坐标. 求 ...

  6. POJ 2404 Jogging Trails(最小权完美匹配)

    [题目链接] http://poj.org/problem?id=2404 [题目大意] 给出一张图,求走遍所有的路径至少一次,并且回到出发点所需要走的最短路程 [题解] 如果图中所有点为偶点,那么一 ...

  7. uva 1411 Ants (权值和最小的完美匹配---KM算法)

    uva 1411 Ants Description Young naturalist Bill studies ants in school. His ants feed on plant-louse ...

  8. [ACM] POJ 3686 The Windy&#39;s (二分图最小权匹配,KM算法,特殊建图)

    The Windy's Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 4158   Accepted: 1777 Descr ...

  9. HDU(1853),最小权匹配,KM

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1853 Cyclic Tour Time Limit: 1000/1000 MS (Java/Other ...

随机推荐

  1. mysql中int、bigint、smallint 和 tinyint的区别

    使用整数数据的精确数字数据类型. bigint 从 -2^63 (-9223372036854775808) 到 2^63-1 (9223372036854775807) 的整型数据(所有数字).存储 ...

  2. 深入研究虚拟机之垃圾收集(GC)算法实现

    一.         What, Why 1.   GC是什么?为什么需要GC GC,全写是Garbage Collection , 即垃圾回收.GC是一种自动内存管理机制.通常我们在需要时手动的分配 ...

  3. DuiLib学习笔记3——颜色探究

    在前面两篇日志已经能使用xml了.今天准备好好的折腾一番,结果在颜色上却掉坑里了. 起初我在ps里取颜色为0104ff 这里01为R,04为G,ff为B 在控件的属性里有这样一个属性bkcolor=& ...

  4. JavaScript挑战复杂报表——1总述

    今天用自己写的库完成了一个40列填报报表的前后台调试,所花费的时间超过预期很多.遇到的坑有:ajax回调函数写错导致循环调用,没有考虑到java的request.getParameter()方法读入数 ...

  5. C语言通用双向循环链表操作函数集

    说明 相比Linux内核链表宿主结构可有多个链表结构的优点,本函数集侧重封装性和易用性,而灵活性和效率有所降低.     可基于该函数集方便地构造栈或队列集.     本函数集暂未考虑并发保护. 一  ...

  6. Linq To Sqlite 一一二二

    说在前头 之所以写下这些文字,主要是因为使用LINQ的同志们都觉它的美好(至于有多美好,各位心里知道,我就不在描述了,如果你是你还不了解LINQ,园子里有大把的文章),微软老哥只提供了自家的SQLSe ...

  7. RQNOJ Bus

    H城是一座小城市,前几日才刚刚建立公交系统,且只有一辆公交车.于是,如何最大化这唯一一辆公交车的载客量成了亟待解决的问题. H城的俯视图可以近似地看成是一个棋盘网络——共有N行M列,从南向北,每行从1 ...

  8. asp.net 验证正则表达式

    基本元字符: . 任意的一个非换行字符 [] 集合匹配,匹配一个[]中出现的字符. 是在多个字符中取一个. () 调整优先级的作用. 还有一个分组的作用 | 或的意思,测试|一下. 注意,或的优先级最 ...

  9. 注册、卸载DLL

    注册.卸载DLL,一般命令写在bat文件中,下面以注册.卸载SWFToImage.DLL为例. 1.注册文件(Install.bat)内容: REM copying files to the syst ...

  10. SQL获取第一次出现指定字符前的内容

    update Food set FoodTitle=cast(SUBSTRING(FoodTitle,0,PATINDEX('%的%',FoodTitle)) as nvarchar),FoodCod ...