1. 程式人生 > >“東信杯”廣西大學第一屆程式設計競賽(同步賽)F 出裝方案 【KM 最大權值匹配】

“東信杯”廣西大學第一屆程式設計競賽(同步賽)F 出裝方案 【KM 最大權值匹配】

傳送門:https://ac.nowcoder.com/acm/contest/283/F

題目描述 

眾所周知,在各種對抗類遊戲裡裝備都是很重要的一環,不同的出裝方案會給玩家帶來不同的強度。 dalao手裡有N件裝備,現在dalao要把裝備分給N個隊友,每個隊友只能分一件裝備,而每個隊友穿上不同的裝備會有不同程度的強度提升。 現在給出每個隊友對每件裝備的強度提升的值,請問dalao的所有分配方案裡,最多能讓團隊的總強度提升多少呢?

輸入描述:

第一行有一個整數T,表示資料的組數(不會超過150組) 每組資料第一行包含一個整數N,接下來會有N行,每行有N個整數,其中第 a 行的第 b 個數字表示第 a 個隊友穿上第 b 件裝備的強度提升。任何隊員穿任何裝備的強度提升都不會超過20000。  

輸出描述:

對於每組資料在一行內輸出一個整數表示強度能夠提升的最大值
示例1

輸入

複製
2
4
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
3
1 3 5
2 4 6
7 9 11

輸出

複製
34
16

 

題意概括:如題

解題思路:

呵呵,KM 最大權值匹配。

賽後怒A的一題,這裡留下記錄嘲諷自己,警醒自己。當時在玩蛇呢!!!

 

AC code:

 1 #include <cstdio>
 2 #include <iostream>
 3 #include <cstring>
 4 #include <cmath>
 5 #define INF 0x3f3f3f3f
 6 #define LL long long
 7 using namespace std;
 8 const int MAXN = 310;
 9 int N, nx, ny;
10 int linker[MAXN], lx[MAXN], ly[MAXN], slack[MAXN];
11 int visx[MAXN], visy[MAXN], w[MAXN][MAXN]; 12 13 int Find(int x) 14 { 15 visx[x] = true; 16 for(int y = 1; y <= ny; y++){ 17 if(visy[y]) continue; 18 int ttp = lx[x] + ly[y] -w[x][y]; 19 if(ttp == 0){ 20 visy[y] = true; 21 if(linker[y] == -1 || Find(linker[y])){ 22 linker[y] = x; 23 return true; 24 } 25 } 26 else if(slack[y] > ttp) slack[y] = ttp; 27 } 28 return false; 29 } 30 31 int KM() 32 { 33 memset(linker, -1, sizeof(linker)); 34 memset(ly, 0, sizeof(ly)); 35 for(int i = 1; i <= nx; i++){ 36 lx[i] = -INF; 37 for(int j = 1; j <= ny; j++) 38 if(w[i][j] > lx[i]) lx[i] = w[i][j]; 39 } 40 41 for(int x = 1; x <= nx; x++){ 42 for(int i = 1; i <= ny; i++){ 43 slack[i] = INF; 44 } 45 while(1){ 46 memset(visx, false, sizeof(visx)); 47 memset(visy, false, sizeof(visy)); 48 if(Find(x)) break; 49 50 int d = INF; 51 for(int i = 1; i <= ny; i++) 52 if(!visy[i] && d > slack[i]) 53 d = slack[i]; 54 for(int i = 1; i <= nx; i++) 55 if(visx[i]) lx[i]-=d; 56 for(int j = 1; j <= ny; j++) 57 if(visy[j]) ly[j]+=d; 58 else slack[j]-=d; 59 } 60 } 61 int res = 0; 62 for(int i = 1; i <= ny; i++) 63 if(linker[i] > -1) 64 res+=w[linker[i]][i]; 65 return res; 66 } 67 68 int main() 69 { 70 int T_case; 71 scanf("%d", &T_case); 72 while(T_case--){ 73 scanf("%d", &N); 74 nx = ny = N; 75 for(int i = 1; i <= N; i++) 76 for(int j = 1; j <= N; j++){ 77 scanf("%d", &w[i][j]); 78 } 79 int ans = KM(); 80 printf("%d\n", ans); 81 } 82 }
View Code