zoukankan      html  css  js  c++  java
  • 最小费用最大流解决KM匹配问题

    题目:P1559

    https://www.luogu.com.cn/problem/P1559

    羽毛球队有男女运动员各n人。给定2 个n×n矩阵P和Q。P[i][j]是男运动员i和女运动员j配对组成混合双打的男运动员竞赛优势;Q[i][j]是女运动员i和男运动员j配合的女运动员竞赛优势。由于技术配合和心理状态等各种因素影响,P[i][j]不一定等于Q[j][i]。男运动员i和女运动员j配对组成混合双打的男女双方竞赛优势为P[i][j]*Q[j][i]。设计一个算法,计算男女运动员最佳配对法,使各组男女双方竞赛优势的总和达到最大。

     方法:

      加超级源S, 超级汇T。S向每位男运动员连容量1,费用0的边,每位女运动员向超级汇连接容量1,费用0的边,每位男运动员向女运动员连接容量1,费用为竞赛优势的边,跑最大费用最大流。用SPFA找增广路径。

    代码:

    #include <bits/stdc++.h>
    using namespace std;
    
    const int maxn=20;
    const int INF=0x3f3f3f3f;
    int q[maxn][maxn];
    int p[maxn][maxn];
    int w[maxn][maxn];
    int n;
    int S,T;
    int dis[100];
    queue<int> qe;
    int inqueue[100];
    int pre[100];
    int minflow[100];
    int resflow;
    int res;
    
    struct Edge{
        int next, from, to, remain,fi;
    }e[1000];
    int head[100];
    int en;
    
    void addEdge(int from, int to, int flow, int fi){
        e[en].next=head[from];
        e[en].from=from;
        e[en].to=to;
        e[en].remain=flow;
        e[en].fi=fi;
        head[from]=en;
        ++en;
    }
    
    void add(int from, int to, int flow, int fi){
        addEdge(from,to,flow,fi);
        addEdge(to,from,0,-fi);
    }
    
    void spfa(){
        memset(dis,128,sizeof(dis));
        memset(pre,-1,sizeof(pre));
        memset(minflow,0,sizeof(minflow));
    
        minflow[S]=INF;
        dis[S]=0;
        qe.push(S);
        inqueue[S]=1;
        while(!qe.empty()){
            int cur=qe.front();
            qe.pop();
            inqueue[cur]=0;
            for(int i=head[cur];i!=-1;i=e[i].next){
                int v=e[i].to;
                int c=e[i].fi;
                if(e[i].remain>0 && dis[v]<dis[cur]+c){
                    minflow[v]=min(minflow[cur],e[i].remain);
                    dis[v]=dis[cur]+c;
                    pre[v]=i;
                    if(!inqueue[v]){
                        inqueue[v]=1;
                        qe.push(v);
                    }
                }
            }
        }
    }
    
    void EK(){
        while(true){
            spfa();
            if(pre[T]==-1) break;
    
            int v=T;
            while(true){
                int edge=pre[v];
                if(edge==-1) break;
                e[edge].remain-=minflow[T];
                e[edge^1].remain+=minflow[T];
                v=e[edge].from;
            }
            resflow+=minflow[T];
            res+=minflow[T]*dis[T];
        }
    }
    
    int main(){
        memset(head,-1,sizeof(head));
        res=0;
        resflow=0;
        scanf("%d", &n);
        for(int i=1;i<=n;++i){
            for(int j=1;j<=n;++j){
                scanf("%d", &p[i][j]);
            }
        }
        for(int i=1;i<=n;++i){
            for(int j=1;j<=n;++j){
                scanf("%d", &q[i][j]);
            }
        }
        for(int i=1;i<=n;++i){
            for(int j=1;j<=n;++j){
                w[i][j]=p[i][j]*q[j][i];
            }
        }
        S=0;
        T=2*n+1;
        for(int i=1;i<=n;++i){
            add(S,i,1,0);
            add(i+n,T,1,0);
        }
        for(int i=1;i<=n;++i){
            for(int j=1;j<=n;++j){
                add(i,j+n,1,w[i][j]);
            }
        }
        EK();
        printf("%d", res);
        return 0;
    }  
  • 相关阅读:
    【转】HTML CANVAS
    【转】JY 博客
    【转发】如何使用NPM?CNPM又是什么?
    【转廖大神】package.json 包安装
    【转】Socket接收字节缓冲区
    C# 串口操作系列(5)--通讯库雏形
    C# 串口操作系列(3) -- 协议篇,二进制协议数据解析
    C# 串口操作系列(4) -- 协议篇,文本协议数据解析
    .netCore微服务使用Nginx集中式管理实现
    nginx代理访问及上传文件异常413 Request Entity Too Large
  • 原文地址:https://www.cnblogs.com/FEIIEF/p/12242094.html
Copyright © 2011-2022 走看看