现在的位置: 首页 > 综合 > 正文

joj 2656: 霍格瓦兹魔法阵 最小割

2013年09月01日 ⁄ 综合 ⁄ 共 2420字 ⁄ 字号 评论关闭

最近,伏地魔开始网罗党羽, 许多女巫和男巫为了获得他赋予的力量加入了他的阵营。为了抵抗伏地魔的进攻,霍格瓦兹的魔法师们摆出了一个 n * m 方格的魔法方阵,每个方格中都站有一位魔法师。 当然,魔法师们都有自己的魔法值,用非负整数表示。 然而,对伏地魔发起攻击时,为了安全起见,任意两个相邻的魔法师 (上下相邻或左右相邻) 不能同时施展魔法。为了打败强大的伏地魔,你能帮助霍格瓦兹的魔法师们找出最大可能的攻击魔法值么?

Input

输入含有多组case 每个case的第一行有两个整数 n 和 m ,代表魔法方阵的规模 接下来输入的是 n * m 的非负整数矩阵。 n和m均不超过50 当n=m=0时,输入结束

Output

对每个case, 输出最大可能魔法值

Input

3 2
1 2
3 4
5 6

3 3
75 15 21 
75 15 28 
34 70 5

0 0

Output

11
188

//

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=21010;
const int M=250000;
const int inf=(1<<28);
int head[N];
struct Edge
{
    int u,v,next,w;
} edge[M];
int cnt,n,s,t;//n从0开始  0->n-1
void addedge(int u,int v,int w)
{
    edge[cnt].u=u;
    edge[cnt].v=v;
    edge[cnt].w=w;
    edge[cnt].next=head[u];
    head[u]=cnt++;
    edge[cnt].u=v;
    edge[cnt].v=u;
    edge[cnt].w=0;
    edge[cnt].next=head[v];
    head[v]=cnt++;
}
int sap()
{
    int pre[N],cur[N],dis[N],gap[N];
    int flow=0,aug=inf,u;
    bool flag;
    for(int i=0; i<n; i++)
    {
        cur[i]=head[i];
        gap[i]=dis[i]=0;
    }
    gap[s]=n;
    u=pre[s]=s;
    while(dis[s]<n)
    {
        flag=0;
        for(int &j=cur[u]; j!=-1; j=edge[j].next)
        {
            int v=edge[j].v;
            if(edge[j].w>0&&dis[u]==dis[v]+1)
            {
                flag=1;
                if(edge[j].w<aug) aug=edge[j].w;
                pre[v]=u;
                u=v;
                if(u==t)
                {
                    flow+=aug;
                    while(u!=s)
                    {
                        u=pre[u];
                        edge[cur[u]].w-=aug;
                        edge[cur[u]^1].w+=aug;
                    }
                    aug=inf;
                }
                break;
            }
        }
        if(flag) continue;
        int mindis=n;
        for(int j=head[u]; j!=-1; j=edge[j].next)
        {
            int v=edge[j].v;
            if(edge[j].w>0&&dis[v]<mindis)
            {
                mindis=dis[v];
                cur[u]=j;
            }
        }
        if((--gap[dis[u]])==0)
            break;
        gap[dis[u]=mindis+1]++;
        u=pre[u];
    }
    return flow;
}

//初始化  cnt=0;memset(head,-1,sizeof(head));
//int u=i+j; u的奇偶性相同则不会相交,否则相交
int xx[4]={0,0,1,-1};
int yy[4]={1,-1,0,0};
int main()
{
    int r,c;
    while(scanf("%d%d",&r,&c)==2&&r)
    {
        cnt=0;
        memset(head,-1,sizeof(head));
        n=r*c+2;
        s=0,t=n-1;
        int sum=0;
        for(int i=1;i<=r;i++)
        {
            for(int j=1;j<=c;j++)
            {
                int x;scanf("%d",&x);
                sum+=x;
                int pos=(i-1)*c+j;
                if((i+j)%2)
                {
                    addedge(s,pos,x);
                    for(int k=0;k<4;k++)
                    {
                        int x=i+xx[k],y=j+yy[k];
                        if(x>=1&&x<=r&&y>=1&&y<=c)
                        {
                            addedge(pos,(x-1)*c+y,inf);
                        }
                    }
                }
                else addedge(pos,t,x);
            }
        }
        int ans=sap();
        printf("%d\n",sum-ans);
    }
    return 0;
}

抱歉!评论已关闭.