2014 编程之美 预赛第三题 格格取数 上下界费用流

来源:互联网 发布:怎么加盟在淘宝网店 编辑:程序博客网 时间:2024/04/29 04:19

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

源点向每个行节点连接下界为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_backusing 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\n",sum,ans);    }    return 0;}


 

0 0
原创粉丝点击