#include <memory.h>
#include <iostream>
#include <limits.h>
#include <float.h>
#include <math.h>
//#define min(a, b) ((a) < (b))? (a):(b)
#define PRECISON 0.0000001
#define DOUBLE_MIN(a, b) (((a) - (b)) < PRECISON)? (a):(b)
static const int MAX = 1024;
static int n = 1;
// X 到 Y 的映射(权重)
/*double weight[MAX][MAX] = {{3.1, 4.1, 6.00001, 4.0009, 9.0002, 7.0001, 19.1, 40.01, 22.09, 11.007},
{6, 4, 5, 3, 8, 10, 13, 19, 17, 7 },
{7, 5, 3, 4, 2, 8, 1, 6, 9, 10},
{6, 3, 2, 2, 5, 99, 22, 44, 66, 9 },
{8, 4, 5, 4, 7, 8, 23, 17, 15, 14},
{1, 2, 4, 5, 34, 3, 9, 10, 27, 53},
{9, 3, 33, 32,19, 7, 43, 97, 2, 11},
{2, 34, 9, 43,22, 13, 19, 37, 61, 10},
{3, 90, 122,34,87, 95, 56, 98, 35, 77},
{45, 23, 9, 7, 5, 32, 5, 28, 43, 17}
};*/
double weight[MAX][MAX] =
{{ 50.500000, 81.500000, 218.500000, 368.000000, 519.500000, 811.500000, 696.000000, 1360.000000, 1201.000000, 1336.000000, 1757.500000, 2063.500000, 2171.500000, 2190.000000, 2265.000000, 1519.500000, 1900.000000, 1931.500000, 2080.500000, 2140.500000, 2338.500000, 1974.500000},
{ 195.500000, 65.500000, 72.500000, 223.000000, 373.500000, 666.500000, 550.000000, 1215.000000, 1056.000000, 1191.000000, 1612.500000, 1918.500000, 2026.500000, 2045.000000, 2120.000000, 1373.500000, 1754.000000, 1785.500000, 1934.500000, 1994.500000, 2192.500000, 1828.500000},
{ 316.000000, 188.000000, 50.000000, 107.500000, 258.000000, 551.000000, 433.500000, 1099.500000, 940.500000, 1075.500000, 1497.000000, 1803.000000, 1911.000000, 1929.500000, 2004.500000, 1251.000000, 1631.500000, 1663.000000, 1812.000000, 1872.000000, 2070.000000, 1713.000000},
{ 498.500000, 369.500000, 231.500000, 94.000000, 70.500000, 363.500000, 246.000000, 912.000000, 753.000000, 888.000000, 1309.500000, 1615.500000, 1723.500000, 1742.000000, 1817.000000, 1069.500000, 1450.000000, 1481.500000, 1630.500000, 1690.500000, 1888.500000, 1525.500000},
{ 773.000000, 641.000000, 506.000000, 354.500000, 204.000000, 89.000000, 192.500000, 637.500000, 478.500000, 613.500000, 1035.000000, 1341.000000, 1449.000000, 1467.500000, 1542.500000, 1016.000000, 1396.500000, 1428.000000, 1577.000000, 1637.000000, 1835.000000, 1471.000000},
{ 707.000000, 579.000000, 441.000000, 303.500000, 140.000000, 167.000000, 37.500000, 703.500000, 544.500000, 679.500000, 1101.000000, 1407.000000, 1515.000000, 1533.500000, 1608.500000, 860.000000, 1240.500000, 1272.000000, 1421.000000, 1481.000000, 1679.000000, 1317.000000},
{ 1378.000000, 1246.000000, 1111.000000, 959.500000, 809.000000, 516.000000, 633.500000, 36.500000, 326.500000, 462.500000, 884.000000, 1190.000000, 1206.000000, 1314.500000, 1390.500000, 1374.000000, 1754.500000, 1786.000000, 1935.000000, 1995.000000, 2193.000000, 1829.000000},
{ 1214.000000, 1082.000000, 947.000000, 795.500000, 645.000000, 352.000000, 469.500000, 254.500000, 37.500000, 172.500000, 594.000000, 900.000000, 1008.000000, 1026.500000, 1101.500000, 1083.000000, 1463.500000, 1495.000000, 1644.000000, 1704.000000, 1902.000000, 1538.000000},
{ 1382.000000, 1250.000000, 1115.000000, 963.500000, 813.000000, 520.000000, 637.500000, 421.500000, 131.500000, 4.500000, 426.000000, 732.000000, 840.000000, 858.500000, 933.500000, 916.000000, 1296.500000, 1328.000000, 1477.000000, 1537.000000, 1735.000000, 1371.000000},
{ 1671.500000, 1539.500000, 1404.500000, 1253.000000, 1102.500000, 809.500000, 927.000000, 711.000000, 421.000000, 285.000000, 136.500000, 442.500000, 550.500000, 569.000000, 644.000000, 833.500000, 1007.000000, 1038.500000, 1187.500000, 1247.500000, 1445.500000, 1081.500000},
{ 1946.500000, 1814.500000, 1679.500000, 1528.000000, 1377.500000, 1084.500000, 1202.000000, 986.000000, 696.000000, 560.000000, 138.500000, 167.500000, 275.500000, 294.000000, 369.000000, 1108.500000, 761.000000, 763.500000, 912.500000, 972.500000, 1170.500000, 806.500000},
{ 2158.000000, 2026.000000, 1891.000000, 1739.500000, 1589.000000, 1296.000000, 1413.500000, 1198.500000, 908.500000, 772.500000, 351.000000, 45.000000, 64.000000, 82.500000, 157.500000, 1320.000000, 972.500000, 908.000000, 892.000000, 760.000000, 958.000000, 594.000000},
{ 2233.000000, 2101.000000, 1966.000000, 1814.500000, 1664.000000, 1371.000000, 1488.500000, 1273.500000, 983.500000, 847.500000, 426.000000, 120.000000, 104.000000, 7.500000, 82.500000, 1395.000000, 1047.500000, 983.000000, 967.000000, 773.000000, 883.000000, 519.000000},
{ 2307.500000, 2175.500000, 2040.500000, 1889.000000, 1738.500000, 1445.500000, 1563.000000, 1345.000000, 1056.000000, 921.000000, 499.500000, 193.500000, 175.500000, 67.000000, 9.000000, 1469.500000, 1122.000000, 1057.500000, 1041.500000, 847.500000, 811.500000, 447.500000},
{ 2511.500000, 2379.500000, 2244.500000, 2093.000000, 1942.500000, 1649.500000, 1767.000000, 1221.000000, 1260.000000, 1125.000000, 703.500000, 397.500000, 289.500000, 271.000000, 196.000000, 1673.500000, 1326.000000, 1261.500000, 1245.500000, 1051.500000, 995.500000, 571.500000},
{ 2384.500000, 2252.500000, 2117.500000, 1966.000000, 1815.500000, 1522.500000, 1640.000000, 1424.000000, 1134.000000, 998.000000, 576.500000, 270.500000, 254.500000, 146.000000, 70.000000, 1546.500000, 1199.000000, 1134.500000, 1118.500000, 924.500000, 868.500000, 368.500000},
{ 1320.000000, 1192.000000, 1054.000000, 916.500000, 753.000000, 780.000000, 576.500000, 1090.500000, 800.500000, 795.500000, 1217.000000, 1523.000000, 1631.000000, 1649.500000, 1724.500000, 247.000000, 627.500000, 659.000000, 808.000000, 869.000000, 1066.000000, 1433.000000},
{ 1626.500000, 1498.500000, 1360.500000, 1223.000000, 1059.500000, 1086.500000, 883.000000, 1397.000000, 1107.000000, 971.000000, 911.500000, 1217.500000, 1325.500000, 1344.000000, 1419.000000, 59.500000, 321.000000, 353.500000, 501.500000, 563.500000, 759.500000, 1127.500000},
{ 1996.000000, 1868.000000, 1730.000000, 1592.500000, 1429.000000, 1456.000000, 1252.500000, 1766.500000, 1476.500000, 1340.500000, 919.000000, 848.000000, 956.000000, 974.500000, 1049.500000, 429.000000, 80.500000, 17.000000, 132.000000, 194.000000, 390.000000, 758.000000},
{ 2302.500000, 2174.500000, 2036.500000, 1899.000000, 1735.500000, 1762.500000, 1559.000000, 2073.000000, 1783.000000, 1647.000000, 1225.500000, 919.500000, 903.500000, 795.000000, 742.000000, 735.500000, 388.000000, 323.500000, 307.500000, 114.500000, 83.500000, 450.500000},
{ 2079.500000, 1947.500000, 1812.500000, 1671.000000, 1510.500000, 1534.500000, 1335.000000, 1845.000000, 1555.000000, 1419.000000, 997.500000, 691.500000, 675.500000, 567.000000, 491.000000, 1241.500000, 894.000000, 829.500000, 813.500000, 619.500000, 563.500000, 55.500000},
{ 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000}};
/*
double lx [MAX], ly [MAX]; // 标号
bool sx [MAX], sy [MAX]; // 是否被搜索过
int match [MAX]; // Y(i) 与 X(match [i]) 匹配
*/
bool path (int u, bool *sx, bool *sy, double *lx, double *ly, int *match, double weight[][MAX], int n);
double bestmatch (bool *sx, bool *sy, double *lx, double *ly, int *match, double weight[][MAX], int n, bool maxsum); //maxsum = true表示找权值之和最大的,maxsum = false,表示找 //权值之和最小的
using namespace std;
int main(void)
{
double *lx = NULL, *ly = NULL;
bool *sx = NULL, *sy = NULL;
double sum;
int i, *match = NULL, n = 50;
//if(NULL == (rows = (int *)malloc(sizeof(int) * n))) goto clear;
//if(NULL == (cols = (int *)malloc(sizeof(int) * n))) goto clear;
if(NULL == (match = (int *)malloc(sizeof(int) * n))) goto clear;
if(NULL == (lx = (double *)malloc(sizeof(double) * n))) goto clear;
if(NULL == (ly = (double *)malloc(sizeof(double) * n))) goto clear;
if(NULL == (sx = (bool *)malloc(sizeof(bool) * n))) goto clear;
if(NULL == (sy = (bool *)malloc(sizeof(bool) * n))) goto clear;
memset(match, 0, sizeof(match[0]) * n);
memset(lx, 0, sizeof(lx[0]) * n);
memset(ly, 0, sizeof(ly[0]) * n);
memset(sx, false, sizeof(sx[0]) * n);
memset(sy, false, sizeof(sy[0]) * n);
for(n = 43; n < 50; n++)
{
double cost = bestmatch(sx, sy, lx, ly, match, weight, n, true); //此时求的是最大权值之和,保存在cost中
cout<<"max cost: "<<cost<<endl;
for (i = 0; i < n; i++) //输出顶点集u中的顶点
{
cout<<match[i]<<" ";
}
cout<<endl;
for (i = 0; i < n; i++) //输出顶点集v中与u中”对应的”(一种最优的对应)的顶点集
{
cout<<i<<" ";
}
cout<<endl;
for (i = 0; i < n; i++) //输出匹配的每队顶点之间的权值
{
cout<<weight[match[i]][i]<<" ";
}
cout<<endl;
//int bestmatch (int *sx, int *sy, int *lx, int *ly, int *match, int **weight, int n, bool maxsum)
cost = bestmatch(sx, sy, lx, ly, match, weight, n, false); //此时求的是最大权值之和,保存在cost中
cout<<"min cost: "<<cost<<endl;
for (i = 0; i < n; i++) //输出顶点集u中的顶点
{
cout<<match[i]<<" ";
}
cout<<endl;
for (i = 0; i < n; i++) //输出顶点集v中与u中”对应的”(一种最优的对应)的顶点集
{
cout<<i<<" ";
}
cout<<endl;
for (i = 0; i < n; i++) //输出匹配的每队顶点之间的权值
{
cout<<weight[match[i]][i]<<" ";
}
cout<<endl;
getchar();
}
clear:
free(match);
free(lx);
free(ly);
free(sx);
free(sy);
return 0;
}
//unsigned long counts = 0;
bool path (int u, bool *sx, bool *sy, double *lx, double *ly, int *match, double weight[][MAX], int n) //匈牙利递归算法找一个最大的匹配,但并没有找出最小覆盖,结果保存在
{ //printf("path %ld ", ++counts); //match[]数组中,比如找到了最大匹配是5,则V中的顶点0 1 2 3 4依次对应
sx[u] = true; //U中的match[0] match[1] match[2] match[3] match[4]。注意左边顶点集u,右 //边为顶点集V
for (int v = 0; v < n; v++)
{
if (!sy[v] && fabs(lx[u] + ly[v] - weight[u][v]) < PRECISON)
{
sy[v] = true;
if (match[v] == -1 || path(match[v], sx, sy, lx, ly, match, weight, n))
{
match[v] = u;
return true;
}
}
}
return false;
}
double bestmatch (bool *sx, bool *sy, double *lx, double *ly, int *match, double weight[][MAX], int n, bool maxsum) //这个算法就是km算法,权值之和最小或者最大的最大匹配(本程//序中的案列针对完全二分图的,最大匹配也是完全匹配,否则要对二分图做一定的处理,使之存在完美匹配的情形(一般完全二分图))
{
int i, j;
if (!maxsum)
{
for (i = 0; i < n; i++)
{
for (j = 0; j < n; j++)
{
weight[i][j] = -weight[i][j];
//printf("%d ", weight[i][j]);
//getchar();
}
//printf("\n");
}
}
for (i = 0; i < n; i++)
{
lx[i] = weight[i][0];
}
for (i = 0; i < n; i++)
{
for (j = 1; j < n; j++)
{
if (lx[i] - weight[i][j] < PRECISON)
{
lx[i] = weight[i][j];
}
}
}
memset(match, -1, sizeof(match[0]) * n);
for (int u = 0; u < n; u++)
{
while(1)
{
memset(sx, false, sizeof(sx[0]) * n);
memset(sy, false, sizeof(sy[0]) * n);
//bool path (int u, int *sx, int *sy, int *lx, int *ly, int *match, int **weight, int n)
if (path(u, sx, sy, lx, ly, match, weight, n))
{
//printf("%d ", u);
break;
}
double dx = DBL_MAX;
for (i = 0; i < n; i++)
{
if (sx[i])
{
for (j = 0; j < n; j++)
{
if (!sy[j])
{
dx = DOUBLE_MIN(lx[i] + ly[j] - weight[i][j], dx);
}
}
}
}
for (i = 0; i < n; i++)
{
if (sx[i])
{
lx[i] -= dx;
}
if (sy[i])
{
ly[i] += dx;
}
}
}
}
double sum = 0;
for (i = 0; i < n; i++)
{
sum += weight[match[i]][i];
}
if (!maxsum)
{
sum = -sum;
for (i = 0; i < n; i++)
{
for (j = 0; j < n; j++)
{
weight[i][j] = -weight[i][j];
}
}
}
return sum;
}
km算法示例
最新推荐文章于 2021-09-28 11:13:40 发布