zoukankan      html  css  js  c++  java
  • 2014 编程之美 预赛第三题 格格取数 上下界费用流

    构图比较裸,只是上下界费用流不好做= =

    源点向每个行节点连接下界为1上界为INF费用为0的边,每个列节点向汇点连接下界为1上界为INF费用为0的边,行节点向列节点连接下界为0上界为1费用为该点值的边,求一最小费用可行流就好。

    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<iostream>
    #include<fstream>
    #include<map>
    #include<ctime>
    #include<set>
    #include<queue>
    #include<cmath>
    #include<vector>
    #include<bitset>
    #include<functional>
    #define x first
    #define y second
    #define mp make_pair
    #define pb push_back
    using namespace std;
    
    typedef long long LL;
    typedef double ld;
    
    const LL INF=10000000000000LL;
    const int MAX=100000+10;
    
    int n,m,S,T;
    int s[MAX],t[MAX],a[MAX],C[MAX];
    LL in[MAX];
    
    struct Edge
    {
        int s,t,next;
        LL flow,C,cost;
    }e[MAX*10];
    int begin[MAX],tot;
    
    void addedge(int u,int v,LL C,LL cost)
    {
        e[tot].s=u;e[tot].t=v;e[tot].next=begin[u];begin[u]=tot;
        e[tot].flow=0;e[tot].C=C;e[tot].cost=cost;
        tot++;
    }
    
    void add(int u,int v,LL C,LL cost)
    {
        addedge(u,v,C,cost);
        addedge(v,u,0,-cost);
    }
    
    LL dist[MAX];
    int hash[MAX],come[MAX];
    
    
    int SPFA()
    {
        queue<int> q;
        int i,u,v;
        memset(hash,0,sizeof hash);
        for(i=0;i<=T;++i)dist[i]=INF;
        q.push(S);hash[S]=1;dist[S]=0;come[S]=-1;
        while(!q.empty())
        {
            u=q.front();q.pop();hash[u]=0;
            for(i=begin[u];i!=-1;i=e[i].next)
                if(e[i].C>e[i].flow)
                {
                    v=e[i].t;
                    if(dist[v]>dist[u]+e[i].cost)
                    {
                        dist[v]=dist[u]+e[i].cost,come[v]=i;
                        if(!hash[v])
                            hash[v]=1,q.push(v);
                    }
                }
        }
        return dist[T]!=INF;
    }
    
    int main()
    {
        int Cas;
        scanf("%d",&Cas);
        int sum=0;
        while(Cas--)
        {
            sum++;
            tot=0;
            memset(begin,-1,sizeof (begin));
            memset(in,0,sizeof (in));
            scanf("%d%d",&n,&m);
            int i,j,u;
            S=n+m+2,T=n+m+3;
            add(n+m+1,0,INF,0);
            for(i=1;i<=n;++i)
            {
                add(0,i,INF-1,0);
                in[0]-=1;
                in[i]+=1;
            }
            for(i=1;i<=m;++i)
            {
                add(i+n,m+n+1,INF-1,0);
                in[i+n]-=1;
                in[m+n+1]+=1;
            }
            LL ans=0;
            for(i=1;i<=n;i++)
            {
                for(j=1;j<=m;j++)
                {
                    scanf("%d",&u);
                    add(i,j+n,INF,u);
                }
            }
            for(i=0;i<=n+m+1;++i)
            {
                if(in[i]>0)add(S,i,in[i],0);
                else add(i,T,-in[i],0);
            }
            while(SPFA())
            {
                LL mm=INF;
                int u=T;
                while(u!=S)
                {
                    mm=min(e[come[u]].C-e[come[u]].flow,mm);
                    u=e[come[u]].s;
                }
                ans+=mm*dist[T];
                u=T;
                while(u!=S)
                {
                    e[come[u]].flow+=mm;
                    e[come[u]^1].flow-=mm;
                    u=e[come[u]].s;
                }
            }
            printf("Case %d: %lld
    ",sum,ans);
        }
        return 0;
    }
    


     

  • 相关阅读:
    TCP三次握手和四次挥手
    shell脚本进阶
    shell脚本编程基础
    centos6/7通用查看系统版本
    OSI与TCP/IP网络模型分层
    RAID基础知识总结
    yum的初步了解与使用
    Red Hat Enterprise Linux 官方正式版镜像下载
    MYSQL的基本使用,以及错误代码的意思
    人生第一次研读MFC截图工具的笔记心得
  • 原文地址:https://www.cnblogs.com/vermouth/p/3710140.html
Copyright © 2011-2022 走看看