二分图KM算法 HDU 2255

在百度百科学了KM算法。。

km算法是求完备匹配下的最大权

KM算法流程:

1.对二分图的两部分顶点初始化

2.KM算法用匈牙利算法寻找完备匹配

3.如果未找到就修改相应顶点值

4重复(2)(3)直到找到相等子图的完备匹配为止;

HDU 2255是裸题。。

未优化版:

View Code
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int match[1000];
int mp[400][400];
bool visitx[400], visity[400];
int xx[400], yy[400];
const int inf = 0x7f7f7f7f;
int minx, N;

void init( )
{
memset(match, -1, sizeof(match));
memset(mp, 0, sizeof(mp));
memset(xx, 0, sizeof(xx));
memset(yy, 0, sizeof(yy));
}

bool Hungary( int x)
{
visitx[x] = true;
for( int i = 1; i <= N; i++)
{
if( visity[i] ) continue;
int temp = xx[x] + yy[i] - mp[x][i];
if( temp == 0 )
{
visity[i] = true;
if( match[i] == -1 || Hungary(match[i]))
{
match[i] = x;
return true;
}
}
else
{
if( temp < minx )
minx = temp;
}
}
return false;
}

void KM( )
{
for( int i = 1; i <= N; i++)
{
for( int j = 1; j <= N; j++)
{
if( mp[i][j] > xx[i] )
xx[i] = mp[i][j];
yy[j] = 0;
}
}
for( int i = 1; i <= N; i++)
{
while( 1 )
{
memset(visitx, 0, sizeof(visitx));
memset(visity, 0, sizeof(visity));
minx = inf;
if( Hungary( i ) )
break;
else
{
for(int j = 1; j <= N; j++)
{
if( visitx[j] )
xx[j] -= minx;
if( visity[j] )
yy[j] += minx;

}
}
}
}
int sum = 0;
for( int i = 1; i <= N; i++)
sum += mp[match[i]][i];
printf("%d\n", sum);

}

int main( )
{

while( scanf("%d",&N) != EOF )
{
init( );
for( int i = 1; i <= N; i++)
for( int j = 1; j <= N; j++)
scanf("%d",&mp[i][j]);
KM( );
}
}

优化版,跑出来时间到多一些,囧

 

View Code
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <algorithm>
using namespace std;

int match[310];
int xx[310], yy[310];
int visitx[310], visity[310];
int mp[310][310];
int slack[310];
const int inf = 0x7f7f7f7f;
int N;

void init( )
{
memset(match, -1, sizeof(match));
memset(xx, 0, sizeof(xx));
memset(yy, 0, sizeof(yy));
memset(mp, 0, sizeof(mp));
}

bool Hungary( int x)
{
visitx[x] = true;
for( int i = 1; i <= N; i++)
{
if( visity[i] )
continue;
int temp = xx[x] + yy[i] - mp[x][i];
if( temp == 0)
{
visity[i] = 1;
if( match[i] == -1 || Hungary(match[i]))
{
match[i] = x;
return true;
}
}
else
slack[i] = min(slack[i], temp);
}
return false;
}

void KM( )
{
for( int i = 1; i <= N; i++)
for( int j = 1; j <= N; j++)
{
if( mp[i][j] > xx[i] )
xx[i] = mp[i][j];
yy[j] = 0;
}
for( int i = 1; i <= N; i++)
{
for( int j = 1; j <= N; j++)
slack[j] = inf;
while( 1 )
{
memset(visitx, 0, sizeof(visitx));
memset(visity, 0, sizeof(visity));
if( Hungary(i) )
break;
else
{
int temp = inf;
for( int j = 1; j <= N; j++)
{
if( !visity[j] && slack[j] < temp )
temp = slack[j];
}
for( int k = 1; k <= N; k++)
{
if(visitx[k])
xx[k] -= temp;
if(visity[k])
yy[k] += temp;
else
slack[k] -= temp;
}
}
}
}
int sum = 0;
for( int i = 1; i <= N; i++)
sum += mp[match[i]][i];
printf("%d\n", sum);

}
int main( )
{
while( scanf("%d",&N) != EOF )
{
init( );
for( int i = 1; i <= N; i++)
for( int j = 1; j <= N; j++)
scanf("%d",&mp[i][j]);
KM( );
}
return 0;
}



posted on 2012-03-08 14:11  more think, more gains  阅读(285)  评论(0编辑  收藏  举报

导航