layout: post

title: 训练指南 UVA - 11383(KM算法的应用 lx+ly >=w(x,y))

author: "luowentaoaa"

catalog: true

mathjax: true

tags:

- KM算法

- 训练指南


Golden Tiger Claw

UVA - 11383

题意

给一个n*n的矩阵,每个格子中有正整数w[i[j],试为每行和每列分别确定一个数字row[i]和col[i],使得任意格子w[i][j]<=row[i]+col[j]恒成立。先输row,再输出col,再输出全部总和(总和应尽量小)。

思路

本题与匹配无关,但可以用KM算法解决。

  KM算法中的顶标就是保持了Lx[i]+ly[j]>=g[i[j]再求最大权和匹配的,但这个最大权和并没有关系。我们可以将row[i]看成一个男的,col[i]看成一个女的,这样男女的总数就相等。

  一般来说,Lx[i]或Ly[i]仅需要取该行/列中最大的那个数即可保证满足要求,但是这样太大了,可以通过调整来使得总和更小。而KM算法的过程就是一个调整的过程,每一对匹配的男女的那条边的权值就会满足等号 wi[j]=row[i]+col[j],至少需要一个来满足等号,这样才能保证row[i]+col[j]是达到最小的,即从j列看,col[j]满足条件且最小,从i行看,row[i]满足条件且最小。这刚好与KM算法求最大权和一样。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=998244353;
const int maxn=5e2+50;
const ll inf=1e10;
const ll INF = 1000000000;
const double eps=1e-5;
int g[530][530]; ///存图
int nx,ny; /// 两边点数
bool visx[maxn],visy[maxn];
int slack[maxn];
int linker[maxn]; ///y中各点匹配状态
int lx[maxn],ly[maxn]; /// x,y中的点标号
bool dfs(int x){
visx[x]=true;
for(int y=0;y<ny;y++){
if(visy[y])continue;
int tmp=lx[x]+ly[y]-g[x][y];
if(tmp==0){
visy[y]=true;
if(linker[y]==-1||dfs(linker[y])){
linker[y]=x;return true;
}
}
else if(slack[y]>tmp)slack[y]=tmp;
}
return false;
}
int KM(){
memset(linker,-1,sizeof(linker));
memset(ly,0,sizeof(ly));
for(int i=0;i<nx;i++){
lx[i]=-inf;
for(int j=0;j<ny;j++){
if(g[i][j]>lx[i])lx[i]=g[i][j];
}
}
for(int x=0;x<nx;x++){
for(int i=0;i<ny;i++)slack[i]=inf;
while(true){
memset(visx,false,sizeof(visx));
memset(visy,false,sizeof(visy));
if(dfs(x))break;
int d=inf;
for(int i=0;i<ny;i++)
if(!visy[i]&&d>slack[i])d=slack[i];
for(int i=0;i<nx;i++)
if(visx[i])lx[i]-=d;
for(int i=0;i<ny;i++)
if(visy[i])ly[i]+=d;
else slack[i]-=d;
}
}
int res=0;
for(int i=0;i<ny;i++)
if(linker[i]!=-1)res+=g[linker[i]][i];
return res;
} int main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
int n;
while(cin>>n){
nx=ny=n;
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)cin>>g[i][j];
int ans=KM();
cout<<lx[0];
for(int i=1;i<n;i++)cout<<" "<<lx[i];cout<<endl;
cout<<ly[0];
for(int i=1;i<n;i++)cout<<" "<<ly[i];cout<<endl;
cout<<ans<<endl;
} return 0;
}

训练指南 UVA - 11383(KM算法的应用 lx+ly >=w(x,y))的更多相关文章

  1. 训练指南 UVA - 11419(二分图最小覆盖数)

    layout: post title: 训练指南 UVA - 11419(二分图最小覆盖数) author: "luowentaoaa" catalog: true mathjax ...

  2. 训练指南 UVA - 11354(最小生成树 + 倍增LCA)

    layout: post title: 训练指南 UVA - 11354(最小生成树 + 倍增LCA) author: "luowentaoaa" catalog: true ma ...

  3. 训练指南 UVA - 11478(最短路BellmanFord+ 二分+ 差分约束)

    layout: post title: 训练指南 UVA - 11478(最短路BellmanFord+ 二分+ 差分约束) author: "luowentaoaa" catal ...

  4. 训练指南 UVA - 11090(最短路BellmanFord+ 二分判负环)

    layout: post title: 训练指南 UVA - 11090(最短路BellmanFord+ 二分判负环) author: "luowentaoaa" catalog: ...

  5. 训练指南 UVA - 10917(最短路Dijkstra + 基础DP)

    layout: post title: 训练指南 UVA - 10917(最短路Dijkstra + 基础DP) author: "luowentaoaa" catalog: tr ...

  6. 训练指南 UVA - 11374(最短路Dijkstra + 记录路径 + 模板)

    layout: post title: 训练指南 UVA - 11374(最短路Dijkstra + 记录路径 + 模板) author: "luowentaoaa" catalo ...

  7. 训练指南 UVA - 11324(双连通分量 + 缩点+ 基础DP)

    layout: post title: 训练指南 UVA - 11324(双连通分量 + 缩点+ 基础DP) author: "luowentaoaa" catalog: true ...

  8. 算法竞赛入门经典训练指南——UVA 11300 preading the Wealth

    A Communist regime is trying to redistribute wealth in a village. They have have decided to sit ever ...

  9. 【UVA 11383】 Golden Tiger Claw (KM算法副产物)

    Omi, Raymondo, Clay and Kimiko are on new adventure- in search of new Shen Gong Wu. But EvilBoy Geni ...

随机推荐

  1. 【转】如何解决每次打开office2010都会出现正在配置以及使用KMS

    转自:http://jingyan.baidu.com/article/90895e0fb1525964ec6b0bb5.html 一.使用mini-KMS_Activator_v1.2_Office ...

  2. hdu3068最长回文(Manacher算法)

    简单来说这是个很水的东西.有点dp的思想吧.推荐两个博客,很详细. http://blog.csdn.net/xingyeyongheng/article/details/9310555 http:/ ...

  3. [NOIP2016]愤怒的小鸟 DP

    ---题面--- 题解: 首先观察数据范围,n <= 18,很明显是状压DP.所以设f[i]表示状态为i时的最小代价.然后考虑转移. 注意到出发点(0, 0)已经被固定,因此只需要2点就可以确定 ...

  4. BZOJ2729 [HNOI2012]排队 【高精 + 组合数学】

    题目链接 BZOJ2729 题解 高考数学题... 我们先把老师看做男生,女生插空站 如果两个老师相邻,我们把他们看做一个男生,女生插空站 对于\(n\)个男生\(m\)个女生的方案数: \[n!m! ...

  5. poj1185 炮兵阵地 状压dp

    司令部的将军们打算在N*M的网格地图上部署他们的炮兵部队.一个N*M的地图由N行M列组成,地图的每一格可能是山地(用"H" 表示),也可能是平原(用"P"表示) ...

  6. 手动安装GCC

    01sunxiaoqiang的博客 Centos离线手动安装gcc.g++教程 转载 2016-11-06 17:35:18 标签:linux应用笔记 在安装LINUX系统的时候很可能会没有安装gcc ...

  7. ZooKeeper Watcher注意事项

    zookeeper watch的定义如下:watch事件是一次性触发器,当watch监视的数据发生变化时,通知设置了该watch的client,即watcher. 需要注意三点: 1.一次性触发器 c ...

  8. tomcat 配置文件中设置JAVA_HOME

    Tomcat默认情况下会用系统的环境变量中找到JAVA_HOME和JRE_HOME.但是有的时候我们需要不同版本的JDK共存. 可以在${TOMCAT_HOME}/bin/setclasspath.b ...

  9. 普通table表格样式及代码大全

     普通table表格样式及代码大全(全)(一) 单实线边框表格 <table style="border-collapse: collapse" borderColor=#0 ...

  10. c++(类继承)示例[仅用于弱弱的博主巩固知识点用哦,不好勿喷]

    测试代码: Animals.h: #pragma once #include<string> class Animals { protected: std::string Food; in ...