GYM 101128 F.Landscaping(最小割-Dinic)

来源:互联网 发布:速卖通数据分析网站 编辑:程序博客网 时间:2024/06/08 16:15

Description
一块n*m的草坪,有两种高度的草,#表示较高的草,.表示较矮的草,现在要从左往右和从上往下用收割机收割,在相同高度的草坪上收割机不耗油,当高度变化时需要耗花费为a的油,还可以花费b改变任一块草坪的高度,问这n+m排收割机扫过这块草坪需要的最小花费
Input
第一行四整数n,m,a,b分别表示草坪行列数和两种花费,之后一个n*m矩阵表示该草坪(1<=n,m<=50,1<=a,b<=1e5)
Output
输出最小花费
Sample Input
这里写图片描述
Sample Output
11000
Solution
把高草坪看做一个集合S,矮草坪看做一个集合E,问题可以的当做是把这n*m个点分成这两个集合所需的最小代价,高草坪变成矮草坪和矮草坪变成高草坪花费代价b,每块草坪和其四周的草坪之间花费代价a表示高度变化的代价(同样高度也要连,因为不知道是否要改变其中某块的高度,而且如果两块草坪最终高度相同那么就会被分在同一个集合中,那么这个代价就不会被统计),即为求这个图的最小割
Code

#include<cstdio>#include<iostream>#include<cstring>#include<algorithm>#include<cmath>#include<vector>#include<queue>#include<map>#include<set>#include<ctime>using namespace std;typedef long long ll;#define maxn 3333#define maxm 2222222#define INF 0x3f3f3f3fint head[maxn],cur[maxn],d[maxn],st[maxm],s,e,no;//s为源点,e为汇点,n为点数,no为边数 struct point{    int u,v,flow,next;    point(){};    point(int x,int y,int z,int w):u(x),v(y),next(z),flow(w){};}p[maxm];void add(int x,int y,int z)//从x到y建容量为z的边 {    p[no]=point(x,y,head[x],z);//前向弧,标号为偶     head[x]=no++;    p[no]=point(y,x,head[y],0);//后向弧,标号为奇     head[y]=no++;}void init()//初始化 {    memset(head,-1,sizeof(head));    no=0;}bool bfs(){    int i,x,y;    queue<int>q;    memset(d,-1,sizeof(d));    d[s]=0;     q.push(s);    while(!q.empty())    {        x=q.front();            q.pop();        for(i=head[x];i!=-1;i=p[i].next)        {            if(p[i].flow&& d[y=p[i].v]<0)            {                d[y]=d[x]+1;                if(y==e)                        return true;                q.push(y);            }        }    }    return false;}ll dinic()//最大流 {    int i,loc,top,x=s,nowflow;    ll maxflow=0;    while(bfs())    {        memcpy(cur,head,sizeof(head));        top=0;        while(true)        {            if(x==e)            {                nowflow=INF;                for(i=0;i<top;i++)                {                    if(nowflow>p[st[i]].flow)                    {                        nowflow=p[st[i]].flow;                        loc=i;                    }                }                for(i=0;i<top;i++)                {                    p[st[i]].flow-=nowflow;                    p[st[i]^1].flow+=nowflow;                }                maxflow+=nowflow;                top=loc;                    x=p[st[top]].u;            }            for(i=cur[x];i!=-1;i=p[i].next)                if(p[i].flow&&d[p[i].v]==d[x]+1)                     break;            cur[x]=i;            if(i!=-1)            {                st[top++]=i;                x=p[i].v;            }            else             {                if(!top)                        break;                d[x]=-1;                x=p[st[--top]].u;            }        }    }    return maxflow;}int n,m,a,b;char c[55][55];int dx[]={-1,0,1,0};int dy[]={0,-1,0,1};int main(){    while(~scanf("%d%d%d%d",&n,&m,&a,&b))    {        for(int i=1;i<=n;i++)scanf("%s",c[i]+1);        s=0,e=n*m+1;        init();        for(int i=1;i<=n;i++)            for(int j=1;j<=m;j++)            {                if(c[i][j]=='#')add(s,(i-1)*m+j,b);                else add((i-1)*m+j,e,b);                    for(int k=0;k<4;k++)                {                    int ii=i+dx[k],jj=j+dy[k];                    if(ii<1||ii>n||jj<1||jj>m)continue;                    add((i-1)*m+j,(ii-1)*m+jj,a);                }               }        printf("%I64d\n",dinic());    }    return 0;}
0 0
原创粉丝点击