hdu 4862 KM算法 最小K路径覆盖的模型
来源:互联网 发布:数据库应用教程 编辑:程序博客网 时间:2024/05/17 16:57
http://acm.hdu.edu.cn/showproblem.php?pid=4862
选t<=k次,t条路要经过所有的点一次并且仅仅一次,
建图是问题:
我自己最初就把n*m 个点分别放入X集合以及Y集合,再求最优匹配,然后连样例都过不了,而且其实当时解释不了什么情况下不能得到结果,因为k此这个条件相当于没用上。。。
建图方法:
1、X集合和Y集合都放入n*m+k个点,X中前n*m个点和Y中前n*m个点之间,如果格子里的值相等,权就是(收益-耗费),不等就是(-耗费),因为要的是最大收益,所以初始时,所有点之间权值为-1;
原因:如下图,1->2 2->3 3->1 二分图的边本身不和其他边相连,但是这样的建图方式,使得可以找到连同路径1->2->3
由此学到的一种思维方式:二分图又称作二部图,是图论中的一种特殊模型。 设G=(V,E)是一个无向图,如果顶点V可分割为两个互不相交的子集(A,B),并且图中的每条边(i,j)所关联的两个顶点i和j分别属于这两个不同的顶点集(i in A,j in B),则称图G为一个二分图。但是如果两个子集是一样的,那么就能通过二分图的算法找路径或者连通分量
这样建图需要避免的是1->1,这种自环的情况,导致有些点不能被覆盖,避免的方法就是初始化的时候,因为要的是最大收益,所以把自环的边初始化为最小值,
2、X中后k个点到Y中前n*m个点,权值为0。Y中后k个点到X中前n*m个点,权值也为0。加入的k个点是作为起点和终点,起点到第一个格子不需要耗费
3、X中k个点和Y中k个点一一对应的权值为0 因为允许少于k次把图遍历完成,k个点中,有自环,说明这次不需要用
建图说的应该够清了,以后复习也好用
帖代码:
#include <cstdio>#include <iostream>#include <algorithm>#include <cstring>#include <string>using namespace std;#define rep(i,s,e) for(int i=s;i<e;i++)const int INF = 999999;//const int MAXN = 11*11+150;int n,matv[MAXN][MAXN],mat[MAXN][MAXN],match[MAXN];bool sx[MAXN],sy[MAXN];int lx[MAXN],ly[MAXN];char line[MAXN];inline int ABS(int x){ return x>=0?x:-x;}bool path(int u){ sx[u]=true; rep(v,0,n) if(!sy[v] && lx[u]+ly[v]==mat[u][v]) { sy[v]=1; if(match[v]==-1 || path(match[v])) { match[v]=u; return true; } } return false;}int KM(){ rep(i,0,n) { lx[i]=-INF; ly[i]=0; rep(j,0,n) { lx[i]=max(lx[i],mat[i][j]); } } memset(match, 0xff, sizeof(match)); rep(u,0,n) { while(1) { memset(sx,0,sizeof(sx)); memset(sy,0,sizeof(sy)); if(path(u))break; int dmin=INF; rep(i,0,n) if(sx[i]) rep(j,0,n) if(!sy[j]) dmin=min(lx[i]+ly[j]-mat[i][j],dmin); rep(i,0,n) { if(sx[i]) lx[i]-=dmin; if(sy[i]) ly[i]+=dmin; } } } int sum=0; rep(j,0,n)//// { if(mat[match[j]][j] == -INF)return -INF; sum+=mat[match[j]][j]; } return sum;}void init(int nn, int mm,int kk){ for(int i=0;i<n;i++) for(int j=0;j<n;j++) { mat[i][j]=-INF; } rep(i,nn*mm,n) mat[i][i]=0; rep(i,0,nn) rep(j,0,mm) { rep(ii,0,kk) mat[nn*mm+ii][i*mm+j]=mat[i*mm+j][nn*mm+ii]=0; //right rep(jj,j+1,mm) { if(matv[i][j] == matv[i][jj]) { mat[i*mm+j][i*mm+jj]=matv[i][j]-ABS(j-jj)+1; } else { mat[i*mm+j][i*mm+jj]=-ABS(j-jj)+1; } } //below rep(ii,i+1,nn) { if(matv[i][j] == matv[ii][j]) { mat[i*mm+j][ii*mm+j]=matv[i][j]-ABS(i-ii)+1;//变量写错。。。 } else { mat[i*mm+j][ii*mm+j]=-ABS(i-ii)+1; } } }}int main(){ //freopen("hdu4862.txt","r",stdin); //freopen("out.txt","w",stdout); int ncase; int nn,kk,mm; scanf("%d",&ncase); for(int icase=1;icase<=ncase;icase++) { scanf("%d%d%d",&nn,&mm,&kk); n=nn*mm+kk; rep(i,0,nn) { scanf("%s",line); rep(j,0,mm) { matv[i][j]=line[j]-'0'; } } init(nn,mm,kk); int ans=KM(); if(ans<=-INF)printf("Case %d : -1\n",icase); else printf("Case %d : %d\n", icase, ans); } return 0;}
- hdu 4862 KM算法 最小K路径覆盖的模型
- hdu 4862 Jump(最小k路径覆盖)
- ★ HDU 4862 带费用的最小K路径覆盖
- HDU 4862 Jump 最小k路径覆盖 费用流
- hdu 4862 最小k路径覆盖 费用流
- HDU 4862 Jump (最小K路径覆盖)
- 二分图-最大匹配,最小路径覆盖,最小点覆盖(KM算法)
- hdu 1151 最小覆盖路径算法证明
- HDU tarjan算法模版 强连通分量+最小路径覆盖
- HDU 1151 Air Raid(匈牙利算法 二分图的最小路径覆盖 )
- 【最小路径覆盖】HDU 4160
- hdu 1151 最小路径覆盖
- hdu 1151 最小路径覆盖
- HDU - 4160 最小路径覆盖
- HDU-2255(记录km算法的板子,km求最大权,最小权匹配)
- 【算法学习】最小路径覆盖
- 网络费用流-最小k路径覆盖
- hdu Matrix(二分图的最小路径覆盖)
- Hadoop集群(第1期)_CentOS安装配置
- HDU 2669
- 一淘搜索之网页抓取系统分析与实现(4)- 实现&总结
- A - 简单字符串排序
- USACO--1.2 Transformations
- hdu 4862 KM算法 最小K路径覆盖的模型
- POJ 1141 Brackets Sequence (区间DP)
- Hibernate核心接口
- 【POMELO】深入浅出node.js游戏服务器开发
- 字符编码笔记:ASCII,Unicode和UTF-8
- POJ 3981 字符串替换
- 设计模式之桥接模式 待续
- POJ 1731 Orders
- ACE 多线TCP服务端-客户端通信