hdu3488-(二分图最小权匹配)

来源:互联网 发布:caffe安装 编辑:程序博客网 时间:2024/06/06 23:23

题意:求去掉一些边这个图都是环并且所有的边总权值最小

题解:每条边因为是单向的的而且不会匹配到自己那么不管最后怎么匹配肯定都能形成环那么就是二分图最小权匹配

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int inf = 0x3f3f3f3f;const int mx = 205;int g[mx][mx],lx[mx],ly[mx],vx[mx],vy[mx],y[mx];int n,m;bool find(int u){    vx[u] = 1;    for(int i = 1; i <= n; i++)    if(g[u][i]!=inf&&!vy[i]&&lx[u]+ly[i]==g[u][i]){        vy[i] = 1;        if(!y[i]||find(y[i])){            y[i] = u;            return true;        }    }    return false;}int KM(){    memset(y,0,sizeof(y));    for(int i = 1; i <= n; i++)        for(int j = 1; j <= n; j++)            g[i][j] = -g[i][j];    for(int i = 1; i <= n; i++){        lx[i] = -inf;        ly[i] = 0;        for(int j = 1; j <= n; j++)            if(g[i][j]!=inf)                lx[i] = max(g[i][j],lx[i]);    }    for(int u = 1; u <= n; u++){        while(1){            memset(vx,0,sizeof(vx));            memset(vy,0,sizeof(vy));            if(find(u)) break;            int inc = inf;            for(int i = 1; i <= n; i++)                if(vx[i])                for(int j = 1; j <= n; j++)                    if(!vy[j]&&g[i][j]!=inf)                        inc = min(inc,lx[i]+ly[j]-g[i][j]);            for(int i = 1; i <= n; i++){                if(vx[i])   lx[i] -= inc;                if(vy[i])   ly[i] += inc;            }        }    }    int ans = 0;    for(int i = 1; i <= n; i++)        ans += g[y[i]][i];    return -ans;}int main(){    int t;    scanf("%d",&t);    while(t--){        scanf("%d%d",&n,&m);        memset(g,inf,sizeof(g));        for(int i = 1; i <= m; i++){            int u,v,w;            scanf("%d%d%d",&u,&v,&w);            g[u][v] = min(g[u][v],w);        }        printf("%d\n",KM());    }    return 0;}


阅读全文
0 0
原创粉丝点击