博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
hdu 4862 KM算法 最小K路径覆盖的模型
阅读量:6246 次
发布时间:2019-06-22

本文共 2124 字,大约阅读时间需要 7 分钟。

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 
#include
#include
#include
#include
using namespace std;#define rep(i,s,e) for(int i=s;i
=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

} 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; }

你可能感兴趣的文章
ArcSDE 10.1 的安装
查看>>
python面向对象——方法
查看>>
Python--分析微信好友是否被删除
查看>>
MYSQL一些字符串的处理,如拼接,截取等,便于用在同一字段中多个值的处理...
查看>>
网络工程师
查看>>
在C#下的SQL模糊查询语句 (Visual Studio)
查看>>
第三章 广域通信网
查看>>
xhtml+css基础知识2
查看>>
我的友情链接
查看>>
Java环境变量配置
查看>>
Magent搭建Memcached集群
查看>>
SQL Server远程备份报错:Operating system error 1326
查看>>
域名转移和域名DNS修改
查看>>
域名查找及错误检查
查看>>
JavaScript 字符串处理详解
查看>>
Linux 查看系统硬件信息(实例详解)
查看>>
Linux系统开发8 线程
查看>>
我的友情链接
查看>>
linux安装过程对硬盘进行分区
查看>>
linux安装eclipse集成开发环境
查看>>