Uva1349Optimal Bus Route Design(二分图最佳完美匹配)(最小值)
题意:
给定n个点的有向图问,问能不能找到若干个环,让所有点都在环中,且让权值最小,KM算法求最佳完美匹配,只不过是最小值,所以把边权变成负值,输出时将ans取负即可
这道题是在VJ上交的
#include <iostream> #include <cstring> #include <cstdio> #include <algorithm> using namespace std; const int maxn = 100 + 5; const int inf = 0x3f3f3f3f; bool visr[maxn], visl[maxn]; int n, delta, w[maxn][maxn], lx[maxn], ly[maxn], lft[maxn]; inline bool match( int x ){ visl[x] = 1; for( int y=1; y<=n; y++ ) if( lx[x]+ly[y]==w[x][y] && !visr[y] ){ visr[y] = 1; if( !lft[y] || match(lft[y]) ){ lft[y] = x; return 1; } } return 0; } inline void update(){ for( int i=1; i<=n; i++ ) if( visl[i] ) for( int j=1; j<=n; j++ ) if( !visr[j] ) delta = min( delta, lx[i]+ly[j]-w[i][j] ); for( int i=1; i<=n; i++ ){ if( visl[i] ) lx[i] -= delta; if( visr[i] ) ly[i] += delta; } } inline int KM(){ for( int i=1; i<=n; i++ ){ lft[i] = ly[i] = 0; lx[i] = -inf; for( int j=1; j<=n; j++ ) lx[i] = max(lx[i], w[i][j]); } for( int i=1; i<=n; i++ ){ while(1){ delta = inf; memset( visr, 0, sizeof(visr) ); memset( visl, 0, sizeof(visl) ); if( match(i) ) break; update(); } } int res = 0; for( int i=1; i<=n; i++ ) res += w[lft[i]][i]; return res; } int main(){ // freopen("in.txt", "r", stdin); while( ~scanf("%d", &n) && n ){ for( int i=1; i<=n; i++ ) for( int j=1; j<=n; j++ ) w[i][j] = -inf; //不能使用memset( w, -inf, sizeof(w) ); for( int i=1; i<=n; i++ ){ int j; while( ~scanf("%d", &j) && j ){ int d; scanf("%d", &d); w[i][j] = max( -d, w[i][j] ); } } int ans = KM(); if( -ans>=inf ) puts("N"); else printf("%d\n", -ans); } return 0; }