• 网络流24题-分配问题


    分配问题

    时空限制1000ms / 256MB

    题目描述

    有 n 件工作要分配给 n 个人做。第 i 个人做第 j 件工作产生的效益为 c[i][j]。试设计一个将 n 件工作分配给 n 个人做的分配方案,使产生的总效益最大。

    输入输出格式

    输入格式:

    文件的第 1 行有 1 个正整数 n ,表示有 n 件工作要分配给 n 个人做。

    接下来的 n 行中,每行有 n 个整数 c​​,表示第 i 个人做第 j 件工作产生的效益为 c[i][j] 。

    输出格式:

    两行分别输出最小总效益和最大总效益。

    输入输出样例

    输入样例: 
    5
    2 2 2 1 2
    2 3 1 2 4
    2 0 1 1 1
    2 3 4 3 3
    3 2 1 2 1
    输出样例: 
    5
    14

    说明

    1n100

    一个人只能做一个工作


    二分图多重最优匹配。
    感觉就是费用流,只不过知道模型容易建图了一些。
    #include<bits/stdc++.h>
    #define N 505
    #define INF LLONG_MAX/2 
    using namespace std;
    typedef struct
    {
        int u,v;
        long long flow,cost;
    }ss;
    ss edg[N*N];
    vector<int>edges[N];
    int now_edges=0;
    
    void addedge(int u,int v,long long flow,long long cost)
    {
        edges[u].push_back(now_edges);
        edg[now_edges++]=(ss){u,v,flow,cost};
        edges[v].push_back(now_edges);
        edg[now_edges++]=(ss){v,u,0,-cost};
    }
    
    bool spfa(int s,int t,long long &flow,long long &cost)
    {
    //    printf("%lld %lld
    ",flow,cost);
        long long dis[N];
        for(int i=0;i<N;i++)dis[i]=INF;
        dis[s]=0;
        int vis[N]={0};
        vis[s]=1;
        queue<int>q;
        q.push(s);
        int pre[N]={0};
        long long  maxflow[N]={0};
        maxflow[s]=INF;
        
        while(!q.empty())
        {
            int now=q.front();
            q.pop();
            vis[now]=0;
            
            int Size=edges[now].size();
            for(int i=0;i<Size;i++)
            {
                ss &e=edg[edges[now][i]];
                
                if(e.flow>0&&dis[e.v]>dis[now]+e.cost)
                {
                    dis[e.v]=dis[now]+e.cost;
                    pre[e.v]=edges[now][i];
                    maxflow[e.v]=min(maxflow[now],e.flow);
                    
                    if(!vis[e.v])
                    {
                        q.push(e.v);
                        vis[e.v]=1;
                    }
                }
            }        
        }
        
        if(dis[t]==INF)return false;
        
        flow+=maxflow[t];
        cost+=dis[t]*maxflow[t];
        
        long long now=t;
        while(now!=s)
        {
            edg[pre[now]].flow-=maxflow[t];
            edg[pre[now]^1].flow+=maxflow[t];
            now=edg[pre[now]].u;
        }
        
        
        return true;
    }
    
    void mcmf(int s,int t,long long &flow,long long &cost)
    {
        while(spfa(s,t,flow,cost));
    }
    void init()
    {
        now_edges=0;
        for(int i=0;i<N;i++)edges[i].clear();
    }
    
    int c[505][505];
    
    int main()
    {
        int n,s,t;
        scanf("%d",&n);
        s=2*n+1;
        t=2*n+2;
        for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
        {
            scanf("%d",&c[i][j]);
        }
        
        
        for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)addedge(i,j+n,1,c[i][j]);
        
        for(int i=1;i<=n;i++)
        {
            addedge(s,i,1,0);
            addedge(i+n,t,1,0);
        }
        long long flow=0,cost=0;
        mcmf(s,t,flow,cost);
        printf("%lld
    ",cost);
        
        init();
        
        for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)addedge(i,j+n,1,-c[i][j]);
        
        for(int i=1;i<=n;i++)
        {
            addedge(s,i,1,0);
            addedge(i+n,t,1,0);
        }
        flow=0;
        cost=0;
        mcmf(s,t,flow,cost);
        printf("%lld
    ",-cost);
        return 0;
    }
    View Code
  • 相关阅读:
    展望2018
    Android按下home键后重新打开app进入主activity的问题
    RxJava整合Retrofit遇到的问题总结
    【总结】四种逆元的求法
    【NOIP模板汇总】I Am Me
    【总结】两类素数筛详解
    【NOIP2009】最优贸易
    【SHOI2002】滑雪
    【51NOD1398】等公交
    【复习总结】玫瑰人生 La Vie en Rose
  • 原文地址:https://www.cnblogs.com/tian-luo/p/9536140.html
Copyright © 2020-2023  润新知