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

探讨如何求解在去除某些边后,使图中所有边构成环且总权值最小的问题。针对单向边且不匹配自身的条件,解析其为二分图最小权匹配的特性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

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

#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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值