程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> POJ 2400 KM算法 最小權匹配 回溯輸出所有最優匹配方案

POJ 2400 KM算法 最小權匹配 回溯輸出所有最優匹配方案

編輯:C++入門知識

很蛋疼的一題

首先輸入就很蛋疼, 據網上的神牛們紛紛說題目的矩陣給反了。然後按反著來還真給過了

KM的話 由於是 n與n的匹配,所以直接取負求KM毫無壓力

但是如果兩邊點數不等,據說會有問題   

 

 

[cpp]
#include <iostream>  
#include <cstdio>  
#include <cstring>  
#include <algorithm>  
#include <vector>  
#include <queue>  
#define MAXN 505  
#define MAXM 555555  
#define INF 1000000000  
using namespace std; 
int n, m, ny, nx; 
int w[MAXN][MAXN]; 
int lx[MAXN], ly[MAXN]; 
int linky[MAXN]; 
int visx[MAXN], visy[MAXN]; 
int slack[MAXN], ans; 
int res[MAXN], v[MAXN]; 
bool find(int x) 

    visx[x] = 1; 
    for(int y = 1; y <= ny; y++) 
    { 
        if(visy[y]) continue; 
        int t = lx[x] + ly[y] - w[x][y]; 
        if(t == 0) 
        { 
            visy[y] = 1; 
            if(linky[y] == -1 || find(linky[y])) 
            { 
                linky[y] = x; 
                return true; 
            } 
        } 
        else if(slack[y] > t) slack[y] = t; 
    } 
    return false; 

int KM() 

    memset(linky, -1, sizeof(linky)); 
    for(int i = 1; i <= nx; i++) lx[i] = -INF; 
    memset(ly, 0, sizeof(ly)); 
    for(int i = 1; i <= nx; i++) 
        for(int j = 1; j <= ny; j++) 
            if(w[i][j] > lx[i]) lx[i] = w[i][j]; 
    for(int x = 1; x <= nx; x++) 
    { 
        for(int i = 1; i <= ny; i++) slack[i] = INF; 
        while(true) 
        { 
            memset(visx, 0, sizeof(visx)); 
            memset(visy, 0, sizeof(visy)); 
            if(find(x)) break; 
            int d = INF; 
            for(int i = 1; i <= ny; i++) 
                if(!visy[i]) d = min(d, slack[i]); 
            for(int i = 1; i <= nx; i++) 
                if(visx[i]) lx[i] -=d; 
            for(int i = 1; i <= ny; i++) 
                if(visy[i]) ly[i] += d; 
                    else slack[i] -= d; 
        } 
    } 
    ans = 0; 
    for(int i = 1; i <= ny; i++) 
        if(linky[i] > 0) ans -= w[linky[i]][i]; 
    return ans; 

int cnt; 
void dfs(int u, int sum) 

    if(sum > ans) return; 
    if(u > n) 
    { 
        if(sum != ans) return; 
        printf("Best Pairing %d\n", ++cnt); 
        for(int i = 1; i <= n; i++) 
            printf("Supervisor %d with Employee %d\n", i, res[i]); 
    } 
    else 
    { 
        for(int i = 1; i <= n; i++) 
            if(!v[i]) 
            { 
                res[u] = i; 
                v[i] = 1; 
                dfs(u + 1, sum - w[u][i]); 
                v[i] = 0; 
            } 
    } 

int main() 

    int x, y, z, e, cas = 0, T; 
    scanf("%d", &T); 
    while(T--) 
    { 
        if(cas) printf("\n"); 
        scanf("%d", &n); 
        nx = n, ny = n, m = n; 
        for(int i = 1; i <= n; i++) 
            for(int j = 1; j <= m; j++) 
                w[i][j] = 0; 
        for(int i = 1; i <= n; i++) 
            for(int j = 0; j < n; j++) 
            { 
                scanf("%d", &x); 
                w[x][i] -= j; 
            } 
        for(int i = 1; i <= n; i++) 
            for(int j = 0; j < n; j++) 
            { 
                scanf("%d", &x); 
                w[i][x] -= j; 
            } 
        printf("Data Set %d, Best average difference: %f\n", ++cas, 0.5 * KM() / n); 
        cnt = 0; 
        memset(v, 0, sizeof(v)); 
        dfs(1, 0); 
    } 
    return 0; 


作者:sdj222555

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved