【codevs1227】方格取数2,费用流

来源:互联网 发布:java解压zip文件代码 编辑:程序博客网 时间:2024/05/24 06:12

传送门
写在前面:努力提升写网络流的能力
思路:建图和蚯蚓很相似,不过这里(i,j)拆出的两个点x,y之间的边有花费,实际点(i,j)与(i+1,j),(i,j)与(i,j+1)之间的连边要流量inf费用为0,而且拆出的两个点都要向(i+1,j)(i,j+1)的x点连边,因为可能我们之前已经去过(i,j)的权值,并不能再获取,所以要从x走向下一个x(同样y也可以走向下一个x)
注意:无

#include<bits/stdc++.h>#define inf 0x7fusing namespace std;int ans,n,k,s,t,tot=1,cnt,first[20000],dis[20000],up[20000];bool vis[20000];queue<int>q;struct edge{    int u,v,w,cost,next;}e[40000];struct os{    int x,y,data;}a[102][52];void add(int x,int y,int z,int c){    e[++tot].u=x;    e[tot].v=y;    e[tot].w=z;    e[tot].cost=c;    e[tot].next=first[x];    first[x]=tot;}bool spfa(){    memset(dis,63,sizeof(dis));    memset(up,0,sizeof(up));    dis[s]=0;vis[s]=1;    q.push(s);    while (!q.empty())    {        int k=q.front();        q.pop();        vis[k]=0;        for (int i=first[k];i;i=e[i].next)        if (e[i].w&&dis[e[i].v]>dis[k]+e[i].cost)        {            dis[e[i].v]=dis[k]+e[i].cost;            up[e[i].v]=i;            if (!vis[e[i].v]) vis[e[i].v]=1,q.push(e[i].v);        }    }    return dis[t]<0x7ffff;}void flow(){    int minn=0x7fffffff;    for (int i=up[t];i;i=up[e[i].u])        minn=min(minn,e[i].w);    for (int i=up[t];i;i=up[e[i].u])        e[i].w-=minn,        e[i^1].w+=minn,        ans+=minn*e[i].cost;}main(){    scanf("%d%d",&n,&k);    for (int i=1;i<=n;i++)        for (int j=1;j<=n;j++)            scanf("%d",&a[i][j].data),            a[i][j].data=-a[i][j].data,            a[i][j].x=++cnt,a[i][j].y=++cnt,            add(cnt-1,cnt,1,a[i][j].data),            add(cnt,cnt-1,0,-a[i][j].data);    s=++cnt;t=++cnt;    add(s,1,inf,0);    add(1,s,0,0);    for (int i=1;i<=n;i++)        for (int j=1;j<=n;j++)        {            if (i+1<=n)                add(a[i][j].x,a[i+1][j].x,inf,0),                add(a[i+1][j].x,a[i][j].x,0,0),                add(a[i][j].y,a[i+1][j].x,inf,0),                add(a[i+1][j].x,a[i][j].y,0,0);            if (j+1<=n)                add(a[i][j].x,a[i][j+1].x,inf,0),                add(a[i][j+1].x,a[i][j].x,0,0),                add(a[i][j].y,a[i][j+1].x,inf,0),                add(a[i][j+1].x,a[i][j].y,0,0);        }    add(cnt-2,t,inf,0);    add(t,cnt-2,0,0);    add(cnt-3,t,inf,0);    add(t,cnt-3,0,0);    while (k--&&spfa()) flow();    printf("%d",-ans);}
0 0
原创粉丝点击