zoukankan      html  css  js  c++  java
  • 2011东北地区赛F题(最小费用最大流经典)

    题意:从N个参赛选手中任选2人比赛,胜出的人将获得一定奖金b[i],每个人获胜的次数上限为c[i],给定a[i][j]矩阵,代表i与j需要比a[i][j]次.求要组织完这场赛事至少花费多少钱.赛事无法完成,输出"No,blablabla...".

    构图:最小费用最大流,分别以比赛种类(所有i与j的比赛算一种)、参赛选手为两个集合构造二部图,

    1.源点向比赛种类连费用为0,容量为a[i][j]的边;

    2.参赛选手向汇点连费用为0,容量为获胜次数上限的边;

    3.每种比赛分别向该种比赛(ivsj)的两个参赛选手i,j连费用为相应参赛选手获胜得到的奖金金额b[i]||b[j],容量为a[i][j]的边.

    4.满流处理:只有比赛次数==胜出次数时,即只有胜出次数满流且等于比赛次数时,赛事才能完成,否则输出"No...".

    注意:b[i]为单位次获胜得到的奖金,流量(flow)为获胜次数,总奖金为b[i]*flow.每次增广路操作后,执行ans+=dist[end]*flow计算总费用.

    View Code
    /*Source Code
    Problem: 1000
    Username: 2010201211
    Run Time: 268MS
    Memory: 856K
    Language:C++
    JudgeStatus: Accepted
    */
    #include <iostream>
    #include <stdio.h>
    #include <queue>
    #include <math.h>
    #include <string.h>
    using namespace std;
    #define V 400
    #define E 65000
    #define inf 999999999
    #define infx 99999999999
    int n,m,bs_cnt,sum;
    int vis[V];
    long long dist[V];
    int pre[V];
    
    struct BS{
        int x,y;
    }bs[V];
    
    struct Edge{
        int u,v,c,next;
        long long cost;
    }edge[E*2];
    int head[V],cnt;
    void init(){
        cnt=0;
        memset(head,-1,sizeof(head));
    }
    
    void addedge(int u,int v,int c,long long cost){
        edge[cnt].u=u;edge[cnt].v=v;edge[cnt].cost=cost;
    
        edge[cnt].c=c;edge[cnt].next=head[u];head[u]=cnt++;
    
        edge[cnt].u=v;edge[cnt].v=u;edge[cnt].cost=-cost;
        edge[cnt].c=0;edge[cnt].next=head[v];head[v]=cnt++;
    }
    
    bool spfa(int begin,int end){
        int u,v;
        queue<int> q;
    
        for(int i=0;i<=end+2;i++){
            pre[i]=-1;
            vis[i]=0;
            dist[i]=infx;
        }
        vis[begin]=1;
        dist[begin]=0;
        q.push(begin);
    
        while(!q.empty()){
    
            u=q.front();
            q.pop();
            vis[u]=0;
    
            for(int i=head[u];i!=-1;i=edge[i].next){
                if(edge[i].c>0){
                    v=edge[i].v;
                    if(dist[v]>dist[u]+edge[i].cost){
                        dist[v]=dist[u]+edge[i].cost;
                        pre[v]=i;
                        if(!vis[v]){
                            vis[v]=true;
                            q.push(v);
                        }
                    }
                }
            }
        }
        return dist[end]!=infx;
    }
    
    long long MCMF(int begin,int end){
        long long ans=0;
        int flow;
        int flow_sum=0;
    
        while(spfa(begin,end)){
    
            flow=inf;
            for(int i=pre[end];i!=-1;i=pre[edge[i].u])
                if(edge[i].c<flow)
                    flow=edge[i].c;
            for(int i=pre[end];i!=-1;i=pre[edge[i].u]){
                edge[i].c-=flow;
                edge[i^1].c+=flow;
            }
            ans+=dist[end]*flow;
            //cout << ans << endl;
            flow_sum+=flow;
            //cout << flow_sum << endl;
        }
        if(flow_sum!=sum) return -1;
        else return ans;
    }
    
    int main()
    {
        //freopen("in.txt","r",stdin);
        int a[27][27],c[27];
        long long b[27];
        while(scanf("%d",&n)!=EOF){
            for(int i=1;i<=n;i++)
                for(int j=1;j<=n;j++)
                    cin >> a[i][j];
            for(int i=1;i<=n;i++)
                scanf("%lld",&b[i]);
            for(int i=1;i<=n;i++)
                cin >> c[i];
            int z=0;
            sum=0;
            for(int i=1;i<=n;i++)
                for(int j=i+1;j<=n;j++){
                    if(a[i][j]){
                        z++;
                        bs[z].x=i;
                        bs[z].y=j;
                        sum+=a[i][j];
                    }
                }
            bs_cnt=z;
            init();
            for(int i=1;i<=bs_cnt;i++)
                addedge(0,i,a[bs[i].x][bs[i].y],0);
            for(int i=bs_cnt+1;i<=bs_cnt+n;i++)
                addedge(i,bs_cnt+n+1,c[i-bs_cnt],0);
            for(int i=1;i<=bs_cnt;i++){
                addedge(i,bs[i].x+bs_cnt,a[bs[i].x][bs[i].y],b[bs[i].x]);
                addedge(i,bs[i].y+bs_cnt,a[bs[i].x][bs[i].y],b[bs[i].y]);
            }
            long long res=MCMF(0,bs_cnt+n+1);
            if(res==-1) printf("No,that's worst!!\n");
            else printf("%lld\n",res);
        }
        return 0;
    }
    /*
    Sample Input:
    3
    0 1 1
    1 0 0
    1 0 0
    1 1 1
    1 0 1
    3
    0 1 0
    1 0 1
    0 1 0
    1 1 1
    2 0 0
    Sample Output:
    2
    No,that's worst!!
    */
  • 相关阅读:
    云服务器数据库连接(初始密码)
    springboot打jar包正常无法访问页面
    JAVA项目启动正常,无法访问
    vs快捷键大全(转)
    Effective C#(3)
    单元测试之道C#版(1)
    单元测试之道C#版(2)
    从零开始复习股票知识
    A new languageGo
    单元测试之道C#版(3)
  • 原文地址:https://www.cnblogs.com/markliu/p/2538702.html
Copyright © 2011-2022 走看看