12
12
2015
0

【JSOI2015】圈地

这道题目的模型就是裸的网络流,orz Gold_7,将源点与所有正的方块相连,将所有负的方块与汇点相连,然后将墙连接两个方块,注意要加双向边。

然后假设我们把所有房子都买了,要把两个正负不同的方块分开,要把其中一个不买或者买墙。所以最终答案就是所有房子的利益加起来减去最小割即可。

代码:

 

#include<cstdio>
#include<algorithm>
#define INF 1000000000
using namespace std;
int n,m,u,v,tot,source,sink,vs,cost,edgenum,ans;
int id[210][210],a[210][210],vet[4000010],next[4000010],head[4000010],maxv[4000010],gap[4000010],dis[4000010];
void add(int u,int v,int w)
{
    edgenum++;
    vet[edgenum]=v;
    next[edgenum]=head[u];
    head[u]=edgenum;
    maxv[edgenum]=w;
}
int dfs(int u,int aug)
{
    if (u==sink) return aug;
    int flow=0,mind=vs;
    for (int e=head[u];e;e=next[e])
    {
        int v=vet[e];
        if (maxv[e]<=0) continue;
        if (dis[u]==dis[v]+1)
        {
            int t=dfs(v,min(aug-flow,maxv[e]));
            maxv[e]-=t;
            if (e&1) maxv[e+1]+=t;else maxv[e-1]+=t;
            flow+=t;
            if (dis[source]>=vs) return flow;
            if (flow==aug) break;
        }
        mind=min(mind,dis[v]);
    }
    if (!flow)
    {
        gap[dis[u]]--;
        if (!gap[dis[u]]) dis[source]=vs;
        dis[u]=mind+1;
        gap[dis[u]]++;
    }
    return flow;
}
int maxflow(int s,int t)
{
    int ans=0;
    gap[0]=vs=t+1;
    source=s;sink=t;
    while (dis[source]<vs) ans+=dfs(source,INF);
    return ans;
}
int main()
{
    scanf("%d%d",&n,&m);
    for (int i=1;i<=n;i++)
        for (int j=1;j<=m;j++)
            id[i][j]=++tot;
    tot++;
    for (int i=1;i<=n;i++)
        for (int j=1;j<=m;j++)
        {
            scanf("%d",&a[i][j]);
            if (a[i][j]>0){ans+=a[i][j];add(0,id[i][j],a[i][j]);add(id[i][j],0,0);}else
            if (a[i][j]<0){ans-=a[i][j];add(id[i][j],tot,-a[i][j]);add(tot,id[i][j],0);}
        }
    for (int i=1;i<n;i++)
        for (int j=1;j<=m;j++)
        {
            scanf("%d",&cost);
            u=id[i][j];
            v=id[i+1][j];
            add(u,v,cost);
            add(v,u,cost);
        }
    for (int i=1;i<=n;i++)
        for (int j=1;j<m;j++)
        {
            scanf("%d",&cost);
            u=id[i][j];
            v=id[i][j+1];
            add(u,v,cost);
            add(v,u,cost);
        }
    printf("%d\n",ans-maxflow(0,tot));
}
Category: 网络流 | Tags: | Read Count: 455

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter

Host by is-Programmer.com | Power by Chito 1.3.3 beta | Theme: Aeros 2.0 by TheBuckmaker.com