这是复杂度为O(n^4)
#include
#include
#include
using namespace std ;
const int N = 300 + 11 ;
struct Graph {
int from[N] ;//记录匹配状态
int w[N][N] ;//边权
int lx[N] ,ly[N] ;//点标
bool sx[N] , sy[N] ;
int nx , ny ;//nx左节点的个数,ny右节点的个数
bool match(int u) {
sx[u] = true ;
for(int i = 1; i <= ny ; ++i) {
if(!sy[i] && lx[u] + ly[i] == w[u][i]) {
sy[i] = true ;
if(from[i] == -1 || match(from[i])) {//无数次写成match(i),,,,注意了
from[i] = u ;
return true ;
}
}
}
return false ;
}
void std_fun() {
memset(lx , 0 , sizeof(lx)) ;
memset(ly , 0 , sizeof(ly)) ;
for(int i = 1; i <= nx ;++i) {
for(int j= 1; j <= ny; ++j) {
scanf("%d",&w[i][j]);
lx[i] = max(lx[i] , w[i][j]) ;
}
}
memset(from , -1 , sizeof(from)) ;
for(int k = 1; k <= nx; ++k) {
while(true) {
memset(sx , 0 , sizeof(sx)) ;
memset(sy , 0 , sizeof(sy)) ;
if(match(k)) break ;
int d = (1<<30)-1+(1<<30) ;
for(int i = 1 ; i <= nx ; ++i) {
if(sx[i]) {
for(int j = 1; j <= ny ; ++j) {
if(!sy[j]) {//这里是非,,,,
d = min(d , lx[i] + ly[j] - w[i][j]) ;
}
}
}
}
for(int i = 1; i <= nx; ++i) {
if(sx[i]) lx[i] -= d ;
}
for(int i = 1; i <= ny ; ++i){
if(sy[i]) ly[i] += d ;
}
}
}
int sum = 0 ;
for(int i = 1; i <= ny ; ++i) {
if(from[i] != -1) sum += w[from[i]][i] ;
}
printf("%d\n",sum) ;
}
}g ;
int main() {
int n;
while(scanf("%d",&n)==1) {
g.nx = g.ny = n ;
g.std_fun() ;
}
}
复杂度为O(n^3) :但比上面的只快了100多ms
#include
#include
#include
using namespace std ;
const int N = 300 + 11 ;
struct Graph {
int w[N][N] ;
int lx[N] , ly[N] ;
int from[N] , slack[N] ;//右节点匹配状态,,记录点的权值差
bool sx[N] , sy[N] ;
int nx , ny ;//左右节点数
void std_fun() {
memset(lx , 0 , sizeof(lx)) ;
memset(ly , 0 , sizeof(ly)) ;
for(int i = 1; i <= nx ;++i) {
for(int j = 1; j <= ny ;++j) {
scanf("%d",&w[i][j]) ;
if(w[i][j] > lx[i]) lx[i] = w[i][j] ;
}
}
memset(from , -1 ,sizeof(from)) ;
for(int i = 1; i <= nx ; ++i) {
memset(slack , (1<<6) , sizeof(slack)) ;
while(true) {
memset(sx , 0 , sizeof(sx)) ;
memset(sy , 0 , sizeof(sy)) ;
if(match(i)) break ;
int d = (1<<30) ;
for(int i = 1; i <= ny ; ++i) {
if(!sy[i] && slack[i] < d) d = slack[i] ;
}
for(int i = 1; i <= nx ; ++i) {
if(sx[i]) lx[i] -= d ;
}
for(int i = 1; i <= ny ; ++i) {
if(sy[i]) ly[i] += d ;
//else slack[i] -= d ;//这句应该可以不要,但大神的模板这里有,,,
}
}
}
int sum = 0 ;
for(int i = 1; i <= ny ; ++i) {
if(from[i] != -1) sum += w[from[i]][i] ;
}
printf("%d\n" , sum) ;
}
bool match(int u) {
sx[u] = true ;
for(int i = 1; i <= ny ; ++i) {
if(sy[i]) continue ;
int tmp = lx[u] + ly[i] - w[u][i] ;
if(tmp == 0) {
sy[i] = true ;
if(from[i] == -1 || match(from[i])) {
from[i] = u ;
return true ;
}
}else {
if(slack[i] > tmp) slack[i] = tmp ;
}
}
return false ;
}
}g ;
int main() {
int n ;
while(scanf("%d",&n)==1) {
g.nx = g.ny = n ;
g.std_fun() ;
}
}