HDU-5520-最小费用最大流

来源:互联网 发布:爬虫获取股票数据 编辑:程序博客网 时间:2024/06/05 13:32

https://vjudge.net/contest/166969#problem/L
第一次写这种题。。
感觉还是很巧妙的。先求得花费最小的增广路,然后在进行增广路径。

#include <iostream>#include <cstdio>#include <cstdlib>#include <queue>#include <cstring>/*这道题主要是求,一个花费。可以知道是费用流。固定套路,先求最小花费的那个路,在那个条件下求最大流。关键是建边的过程。*/using namespace std;const int maxn=5005;int m,n;int s,t;const long long INF=1e15;struct Node{      int to;//到达的点       int next;//邻接       long long  flow;//流       long long cap;//容       long long cost;}node[1000005];int head[maxn];long long  dis[maxn];int pre[maxn];int vis[maxn];int len;int N;void add(int a,int b,long long c){    node[len].to=b;    node[len].cap=1;    node[len].flow=0;    node[len].next=head[a];    node[len].cost=c;    head[a]=len++;    node[len].to=a;    node[len].cap=0;    node[len].flow=0;    node[len].next=head[b];    node[len].cost=-c;    head[b]=len++;}bool spfa (int s, int t) {    queue <int> q;    for (int i = 0; i < N; i++) {        dis[i] = INF;        vis[i] = 0;        pre[i] = -1;    }    dis[s] = 0;    vis[s] = 1;    q.push (s);    while (!q.empty ()) {        int u = q.front (); q.pop ();        vis[u] = 0;        for (int i = head[u]; i != -1; i = node[i].next) {            int v = node[i].to;            if (node[i].cap > node[i].flow && dis[v] > dis[u]+node[i].cost) {                dis[v] = dis[u]+node[i].cost;                pre[v] = i;                if (!vis[v]) {                    vis[v] = 1;                    q.push (v);                }            }        }    }    if (pre[t] == -1)        return 0;    else        return 1;}int MCMF (int s, int t,  long long &cost) {    long long  flow = 0;    cost = 0;    while (spfa (s, t)) {       long long  Min = INF;        for (int i = pre[t]; i != -1; i = pre[node[i^1].to]) {            if (Min > node[i].cap-node[i].flow) {                Min = node[i].cap-node[i].flow;            }        }        for (int i = pre[t]; i != -1; i = pre[node[i^1].to]) {            node[i].flow += Min;            node[i^1].flow -= Min;            cost += node[i].cost*Min;        }        flow += Min;    }    return flow;}void init(){   memset(head,-1,sizeof(head));    len=0;}int  get(int a,int b){   return a*n+b;}int main(){   int T;    int  num;    scanf("%d",&T);    for(int ttt=1;ttt<=T;ttt++){         int max1=0;         scanf("%d%d",&m,&n);          t=2*m*n+1;         s=2*m*n;          N=2*m*n+2;          init();         for(int i=0;i<m;i++)             for(int j=0;j<n;j++){                 scanf("%d",&num);                 if(num==0){                    add(s,get(i,j),0);                    add(get(i,j)+m*n,t,0);                    max1++;                 }                 else if(num&1){                    add(s,get(i,j),0);                    max1++;                 }                 else                    add(get(i,j)+n*m,t,0);             }             for(int i=0;i<m-1;i++)             for(int j=0;j<n;j++){                 scanf("%d",&num);                 add(get(i,j),get(i+1,j)+m*n,num);                 add(get(i+1,j),get(i,j)+m*n,num);             }             for(int i=0;i<m;i++)             for(int j=0;j<n-1;j++){                 scanf("%d",&num);                 add(get(i,j),get(i,j+1)+n*m,num);                 add(get(i,j+1),get(i,j)+m*n,num);             }             long long cost=0;            printf("Case #%d: ",ttt);             int ans=MCMF(s,t,cost);             if(ans!=max1){                puts("-1");             }             else                printf("%lld\n",cost);    }    return 0;}
原创粉丝点击