二分图最大权最小权完美匹配模板KM
在网上找了一份挺好的模板,先标一下哦~链接君: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的更多相关文章
- UVA 1349 Optimal Bus Route Design (二分图最小权完美匹配)
恰好属于一个圈,那等价与每个点有唯一的前驱和后继,这让人想到了二分图, 把一个点拆开,点的前驱作为S集和点的后继作为T集,然后连边,跑二分图最小权完美匹配. 写的费用流..最大权完美匹配KM算法没看懂 ...
- hdu1533 Going Home km算法解决最小权完美匹配
Going Home Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total ...
- 紫书 例题11-10 UVa 1349 (二分图最小权完美匹配)
二分图网络流做法 (1)最大基数匹配.源点到每一个X节点连一条容量为1的弧, 每一个Y节点连一条容量为1的弧, 然后每条有向 边连一条弧, 容量为1, 然后跑一遍最大流即可, 最大流即是最大匹配对数 ...
- UVa 1349 (二分图最小权完美匹配) Optimal Bus Route Design
题意: 给出一个有向带权图,找到若干个圈,使得每个点恰好属于一个圈.而且这些圈所有边的权值之和最小. 分析: 每个点恰好属于一个有向圈 就等价于 每个点都有唯一后继. 所以把每个点i拆成两个点,Xi ...
- poj3565 Ants km算法求最小权完美匹配,浮点权值
/** 题目:poj3565 Ants km算法求最小权完美匹配,浮点权值. 链接:http://poj.org/problem?id=3565 题意:给定n个白点的二维坐标,n个黑点的二维坐标. 求 ...
- POJ 2404 Jogging Trails(最小权完美匹配)
[题目链接] http://poj.org/problem?id=2404 [题目大意] 给出一张图,求走遍所有的路径至少一次,并且回到出发点所需要走的最短路程 [题解] 如果图中所有点为偶点,那么一 ...
- uva 1411 Ants (权值和最小的完美匹配---KM算法)
uva 1411 Ants Description Young naturalist Bill studies ants in school. His ants feed on plant-louse ...
- [ACM] POJ 3686 The Windy's (二分图最小权匹配,KM算法,特殊建图)
The Windy's Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 4158 Accepted: 1777 Descr ...
- HDU(1853),最小权匹配,KM
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1853 Cyclic Tour Time Limit: 1000/1000 MS (Java/Other ...
随机推荐
- HTTP协议 keep-alive连接 与 BS(firefox-thttpd)实验
什么是 keep-alive 连接 https://en.wikipedia.org/wiki/HTTP_persistent_connection HTTP persistent connectio ...
- 虚拟主机无法使用fsockopen操作处理方法
一.如何禁用fsockopen()下面是两种常用的禁用fsockopen的方法.1.修改php.ini,将 disable_functions = 后加入 fsockopen2.修改php.ini,将 ...
- innodb数据结构
Jeremy Cole on InnoDB architecture : Efficiently traversing InnoDB B+Trees with the page directory ...
- Team Queue (uva540 队列模拟)
Team Queue Queues and Priority Queues are data structures which are known to most computer scientist ...
- Temporary ASP.NET 拒绝访问
CS0016: 未能写入输出文件“c:\Windows\Microsoft.NET\Framework\v4.0.30319\Temporary ASP.NET Files\root\dd813f66 ...
- Intellij IDEA 快捷键介绍
ctrl-w 使所选表达式逐步增大直到选取整个文件 ctrl+shft+w 逐步减少选中 ctrl-n 可以通过键入类名查找一个类 ctrl-shift-n 可以查找文件 ctrl-e 得到 ...
- JAVA-Semaphore信号灯-可实现维护自身线程访问数
import java.util.Random; import java.util.concurrent.ExecutorService; import java.util.concurrent.Ex ...
- Intent 匹配规则
1.在AndroidManifest.xml中可以为 每个 Activity,Service 设置多个Intent-Filter; 在系统启动和程序安装之后,android会收集AndroidMani ...
- 【Nginx】配置Nginx的负载均衡
参考的优秀文章 tomcat配置文件server.xml详解 AJP协议总结与分析 Using nginx as HTTP load balancer 在本机运行2个Tomcat 现需要运行两个Tom ...
- 从零开始学iPhone开发(5)——使用MapKit
(转)Leonbao:MapKit学习笔记 1.概述插入MapView,设置Delegate(一般为Controller),Annotations记录兴趣位置点(AnnotationView用来显示兴 ...