HDU 2255 奔小康赚大钱 POJ 2195 Going Home 最大权完美匹配 KM算法

两道KM算法模板题 可以作为求最大完美匹配模板

一个是求最大权,一个求最小权 ,最小权可以将所有的边权取相反数,求得最大权之后再取反。

HDU 2255代码:

/*--------------------- #headfile--------------------*/
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
/*----------------------#define----------------------*/
#define DRII(X,Y) int (X),(Y);scanf("%d%d",&(X),&(Y))
#define EXP 2.7182818284590452353602874713527
#define CASET int _;cin>>_;while(_--)
#define RII(X, Y) scanf("%d%d",&(X),&(Y))
#define DRI(X) int (X);scanf("%d", &X)
#define mem(a,b) memset(a,b,sizeof(a))
#define rep(i,n) for(int i=0;i
#define rson o<<1|1,m+1,r
#define PII pair
#define MAX 0x3f3f3f3f
#define lson o<<1,l,m
#define MP make_pair
#define PB push_back
#define SE second
#define FI first
typedef long long ll;
templateT MUL(T x,T y,T P){T F1=0;while(y){if(y&1){F1+=x;if(F1<0||F1>=P)F1-=P;}x<<=1;if(x<0||x>=P)x-=P;y>>=1;}return F1;}
templateT POW(T x,T y,T P){T F1=1;x%=P;while(y){if(y&1)F1=MUL(F1,x,P);x=MUL(x,x,P);y>>=1;}return F1;}
templateT gcd(T x,T y){if(y==0)return x;T z;while(z=x%y)x=y,y=z;return y;}
#define DRIII(X,Y,Z) int (X),(Y),(Z);scanf("%d%d%d",&(X),&(Y),&(Z))
#define RIII(X,Y,Z) scanf("%d%d%d",&(X),&(Y),&(Z))
const double pi = acos(-1.0);
const double eps = 1e-6;
const ll mod = 1000000007ll;
const int M = 100005;
const int N = 315;
using namespace std;

/*----------------------Main-------------------------*/

int n, m;
int mc[N], lx[N], ly[N], sk[N];
int vx[N], vy[N], w[N][N];

bool dfs(int x) {
    vx[x] = 1;
    for(int y = 1; y <= m; y++) {
        if(vy[y]) continue;
        int tmp = lx[x] + ly[y] - w[x][y];
        if(tmp == 0) {
            vy[y] = 1;
            if(mc[y] == -1 || dfs(mc[y])) {
                mc[y] = x;
                return 1;
            }
        } else sk[y] = min(sk[y], tmp);
    }
    return 0;
}

int KM() {
    mem(mc, -1);
    mem(ly, 0);
    for(int i = 1; i <= n; i++) {
        lx[i] = -1e9;
        for(int j = 1; j <= m; j++) {
            lx[i] = max(lx[i], w[i][j]);
        }
    }
    for(int x = 1; x <= n; x++) {
        for(int i = 1; i <= m; i++) sk[i] = 1e9;
        while(1) {
            mem(vx, 0);
            mem(vy, 0);
            if(dfs(x)) break;
            int d = 1e9;
            for(int i = 1; i <= m; i++) if(!vy[i]) d = min(d, sk[i]);
            for(int i = 1; i <= n; i++) if(vx[i]) lx[i] -= d;
            for(int i = 1; i <= m; i++) {
                if(vy[i]) ly[i] += d;
                else sk[i] -= d;
            }
        }
    }
    int res = 0;
    for(int i = 1; i <= m; i++) {
        if(mc[i] != -1) res += w[mc[i]][i];
    }
    return res;
}

void solve() {
    while(RI(n) != EOF) {
        m = n;
        for(int i = 1; i <= n; i++) {
            for(int j = 1; j <= m; j++) {
                RI(w[i][j]);
            }
        }
        printf("%d\n", KM());
    }
}
int main() {
//    freopen("in.txt", "r", stdin);
//    freopen("out.txt", "w", stdout);
//    CASET
    solve();
    return 0;
}

POJ 2195 代码:

/*--------------------- #headfile--------------------*/
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
/*----------------------#define----------------------*/
#define DRII(X,Y) int (X),(Y);scanf("%d%d",&(X),&(Y))
#define EXP 2.7182818284590452353602874713527
#define CASET int _;cin>>_;while(_--)
#define RII(X, Y) scanf("%d%d",&(X),&(Y))
#define DRI(X) int (X);scanf("%d", &X)
#define mem(a,b) memset(a,b,sizeof(a))
#define rep(i,n) for(int i=0;i
#define rson o<<1|1,m+1,r
#define PII pair
#define MAX 0x3f3f3f3f
#define lson o<<1,l,m
#define MP make_pair
#define PB push_back
#define SE second
#define FI first
typedef long long ll;
templateT MUL(T x,T y,T P){T F1=0;while(y){if(y&1){F1+=x;if(F1<0||F1>=P)F1-=P;}x<<=1;if(x<0||x>=P)x-=P;y>>=1;}return F1;}
templateT POW(T x,T y,T P){T F1=1;x%=P;while(y){if(y&1)F1=MUL(F1,x,P);x=MUL(x,x,P);y>>=1;}return F1;}
templateT gcd(T x,T y){if(y==0)return x;T z;while(z=x%y)x=y,y=z;return y;}
#define DRIII(X,Y,Z) int (X),(Y),(Z);scanf("%d%d%d",&(X),&(Y),&(Z))
#define RIII(X,Y,Z) scanf("%d%d%d",&(X),&(Y),&(Z))
const double pi = acos(-1.0);
const double eps = 1e-6;
const ll mod = 1000000007ll;
const int M = 100005;
const int N = 115;
using namespace std;

/*----------------------Main-------------------------*/

int n, m;
int mc[N], lx[N], ly[N], sk[N];
int vx[N], vy[N], w[N][N];

bool dfs(int x) {
    vx[x] = 1;
    for(int y = 1; y <= m; y++) {
        if(vy[y]) continue;
        int tmp = lx[x] + ly[y] - w[x][y];
        if(tmp == 0) {
            vy[y] = 1;
            if(mc[y] == -1 || dfs(mc[y])) {
                mc[y] = x;
                return 1;
            }
        } else sk[y] = min(sk[y], tmp);
    }
    return 0;
}

int KM() {
    mem(mc, -1);
    mem(ly, 0);
    for(int i = 1; i <= n; i++) {
        lx[i] = -1e9;
        for(int j = 1; j <= m; j++) {
            lx[i] = max(lx[i], w[i][j]);
        }
    }
    for(int x = 1; x <= n; x++) {
        for(int i = 1; i <= m; i++) sk[i] = 1e9;
        while(1) {
            mem(vx, 0);
            mem(vy, 0);
            if(dfs(x)) break;
            int d = 1e9;
            for(int i = 1; i <= m; i++) if(!vy[i]) d = min(d, sk[i]);
            for(int i = 1; i <= n; i++) if(vx[i]) lx[i] -= d;
            for(int i = 1; i <= m; i++) {
                if(vy[i]) ly[i] += d;
                else sk[i] -= d;
            }
        }
    }
    int res = 0;
    for(int i = 1; i <= m; i++) {
        if(mc[i] != -1) res += w[mc[i]][i];
    }
    return res;
}
char s[N][N];
int W, H;
int cal(PII a, PII b) {
    return abs(a.FI - b.FI) + abs(a.SE - b.SE);
}
void solve() {

    while(RII(W, H)) {
        if(W == 0) break;
        for(int i = 0; i < W; i++) scanf("%s", s[i]);
        vector v1, v2;
        for(int i = 0; i < W; i++) {
            for(int j = 0; j < H; j++) {
                if(s[i][j] == 'H') v1.PB(MP(i, j));
                if(s[i][j] == 'm') v2.PB(MP(i, j));
            }
        }
        n = m = SZ(v1);
        for(int i = 0; i < n; i++) {
            for(int j = 0; j < m; j++) {
                w[i+1][j+1] = -cal(v1[i], v2[j]);
            }
        }
        printf("%d\n", -KM());
    }
}
int main() {
//    freopen("in.txt", "r", stdin);
//    freopen("out.txt", "w", stdout);
//    CASET
    solve();
    return 0;
}


你可能感兴趣的:(ACM__图论)