UVA 11383 Golden Tiger Claw 金虎爪(KM算法)

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

思路:

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

  1 #include <bits/stdc++.h>
  2 #define LL long LONG_LONG_MAX
  3 #define INF 0x7f7f7f7f
  4 #define LL long long
  5 using namespace std;
  6 const int N=510;
  7
  8 int grid[N][N], girl[N];
  9 int Lx[N], Ly[N], slack[N];
 10 bool S[N], T[N];
 11 int n;
 12
 13 bool DFS(int x)
 14 {
 15     S[x]=true;
 16     for(int i=1; i<=n; i++)
 17     {
 18         if(T[i])    continue;
 19         int tmp=Lx[x]+Ly[i]-grid[x][i];
 20         if(tmp==0)
 21         {
 22             T[i]=true;
 23             if(girl[i]==0 || DFS(girl[i]))
 24             {
 25                 girl[i]=x;
 26                 return true;
 27             }
 28         }
 29         else if(tmp<slack[i])
 30             slack[i]=tmp;
 31     }
 32     return false;
 33 }
 34
 35
 36
 37 int KM()
 38 {
 39     memset(girl, 0, sizeof(girl));
 40     memset(Lx, 0, sizeof(Lx));
 41     memset(Ly, 0, sizeof(Ly));
 42     for(int i=1; i<=n; i++)
 43         for(int j=1; j<=n; j++)
 44             Lx[i]=max(Lx[i], grid[i][j]);
 45
 46     for(int i=1; i<=n; i++) //对于每个树
 47     {
 48         for(int j=1; j<=n; j++) slack[j]=INF;
 49         while(1)
 50         {
 51             memset(S, 0, sizeof(S));
 52             memset(T, 0, sizeof(T));
 53             if( DFS(i) )    break;      //找到匹配的蚂蚁
 54
 55
 56             int d=INF;
 57             for(int j=1; j<=n; j++) //找最小D
 58             {
 59                 if(!T[j] && d>slack[j])
 60                     d=slack[j];
 61             }
 62
 63             for(int j=1; j<=n; j++) //更新树
 64             {
 65                 if(S[j])
 66                     Lx[j]-=d;
 67             }
 68
 69             for(int j=1; j<=n; j++) //更新蚂蚁
 70             {
 71                 if(T[j])    Ly[j]+=d;
 72                 else        slack[j]-=d;
 73             }
 74         }
 75     }
 76     int sum=0;
 77     for(int i=1; i<=n; i++) sum+=Lx[i]+Ly[i];
 78     return sum;
 79 }
 80
 81
 82
 83
 84 int main()
 85 {
 86     freopen("input.txt", "r", stdin);
 87     while(~scanf("%d",&n))
 88     {
 89         memset(grid, 0, sizeof(grid));
 90         for(int i=1; i<=n; i++)
 91             for(int j=1; j<=n; j++)
 92                 scanf("%d",&grid[i][j]);
 93
 94         int ans=KM();
 95         printf("%d", Lx[1]);//值得注意的输出格式。
 96         for(int i=2; i<=n; i++) printf(" %d", Lx[i]);
 97         printf("\n");
 98         printf("%d",Ly[1]);
 99         for(int i=2; i<=n; i++) printf(" %d", Ly[i]);
100         printf("\n");
101         printf("%d\n", ans);
102     }
103     return 0;
104 }

AC代码

时间: 2024-11-06 07:30:46

UVA 11383 Golden Tiger Claw 金虎爪(KM算法)的相关文章

uva 11383 Golden Tiger Claw (KM算法)

uva 11383 Golden Tiger Claw 题目大意:给定一个N×N的矩阵,每个格子里都有一个正整数w(i,j).你的任务是给每行确定一个整数row(i), 每列也确定一个整数col(i),使得对于格子(i,j),w(i,j)<=row(i)+col(j).所有row(i)和col(j)的总和最小. 解题思路:KM算法. #include <cstdio> #include <cstring> #include <algorithm> #include

UVA 11383 - Golden Tiger Claw(二分图完美匹配扩展)

UVA 11383 - Golden Tiger Claw 题目链接 题意:给定每列和每行的和,给定一个矩阵,要求每个格子(x, y)的值小于row(i) + col(j),求一种方案,并且所有行列之和的和最小 思路:A二分图完美匹配的扩展,行列建二分图,权值为矩阵相应位置的值,做一次KM算法后,所有顶标之和就是最小的 代码: #include <cstdio> #include <cstring> #include <cmath> #include <algor

UVA 11383 Golden Tiger Claw

Golden Tiger Claw Time Limit: 8000ms Memory Limit: 131072KB This problem will be judged on UVA. Original ID: 1138364-bit integer IO format: %lld      Java class name: Main Omi, Raymondo, Clay and Kimiko are on new adventure- in search of new Shen Gon

UVA11383 Golden Tiger Claw

题目 UVA11383 Golden Tiger Claw 做法 \(KM\)好题啊,满足所有边\(l(x)+l(y)≥w(x,y)\)(个人理解,如不对请及时留言),这样能满足\(\sum\limits_i^n(l(x)+l(y))\)最小值 My complete code #include<bits/stdc++.h> using namespace std; typedef long long LL; const LL maxn=1e3,inf=0x3f3f3f3f; LL n,mi;

训练指南 UVA - 11383(KM算法的应用 lx+ly &gt;=w(x,y))

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

UVA 11383 KM性质

点击打开链接 题意:一个n*n的矩阵每个格子里有一个正整数w(i,j)你的任务是确定每行一个整数row(i)每列一个整数col(i),对每个格子都有w(i,j)<=row(i)+col(j)所有row(i)和col(i)和尽量小. 思路:本题利用KM算法l(x)+l(y)>=w(x,y)的性质直接可以知道得出的顶标之和即为最小的. #include <stdio.h> #include <string.h> #include <iostream> #incl

UVa 11383 少林决胜(二分图最佳完美匹配)

https://vjudge.net/problem/UVA-11383 题意: 给定一个N×N矩阵,每个格子里都有一个正整数W(i,j).你的任务是给每行确定一个整数row(i),每列也确定一个整数col(i),使得对于任意格子(i,j),w(i,j)<=row(i)+col(j).所有的row(i)和col(i)只和应尽量小. 思路: 利用二分图最佳完美匹配当中的l(x)+l(y)>=w(i,j),直接用KM算法即可. 1 #include<iostream> 2 #inclu

hdoj 3488 Tour 【最小费用最大流】【KM算法】

Tour Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others) Total Submission(s): 2299    Accepted Submission(s): 1151 Problem Description In the kingdom of Henryy, there are N (2 <= N <= 200) cities, with M (M <= 3000

hdu2255 奔小康赚大钱 二分图最佳匹配--KM算法

传说在遥远的地方有一个非常富裕的村落,有一天,村长决定进行制度改革:重新分配房子.这可是一件大事,关系到人民的住房问题啊.村里共有n间房间,刚好有n家老百姓,考虑到每家都要有房住(如果有老百姓没房子住的话,容易引起不安定因素),每家必须分配到一间房子且只能得到一间房子.另一方面,村长和另外的村领导希望得到最大的效益,这样村里的机构才会有钱.由于老百姓都比较富裕,他们都能对每一间房子在他们的经济范围内出一定的价格,比如有3间房子,一家老百姓可以对第一间出10万,对第2间出2万,对第3间出20万.(