//这道题就是方格取数(1)的略微加强。。只是这道的N变成50,用EK应该是会超时的。。
//这道题用EK会TLE,,要用ISPA,DINIC。。。

//所以以后写网络流建议直接写ISPA,或者DINIC,最好是DINIC,因为最快。。
//还有就是要学会黑白染色的两种方法。。
//还有就是模板的灵活运用。。
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
#define inf 0x7FFFFFFF
const int N=2510; //这里比较坑爹,,要开大一点。。
const int INF = 0x7FFFFFFF;
int move[4][2]={0, 1, 0, -1, 1, 0, -1, 0};
int n,m,s,t,dis[N],pre[N],gap[N],flow[N][N]; 

struct edge 

    int v,w; 
    edge *next,*rev; 
    edge(){next=0;} 
    edge(int vv,int ww,edge *e)
 {v=vv;w=ww;next=e;} 
}*adj[N],*path[N],*e; 

int min(int x,int y)
{
 if(x>y)
  return y;
 else
  return x;
}
void insert(int u,int v,int w) 

    edge *p=new edge(v,w,adj[u]); 
    adj[u]=p; 
    edge *q=new edge(u,0,adj[v]); 
    adj[v]=q; 
    p->rev=q; 
    q->rev=p; 

void bfs() 

    memset(dis,0x7f,sizeof(dis)); 
    memset(gap,0,sizeof(gap)); 
    queue<int> q; 
    dis[t]=0; 
    gap[0]=1; 
    q.push(t); 
    while(q.size()) 
    { 
        int x=q.front(); 
        q.pop(); 
        for(e=adj[x];e;e=e->next) 
        { 
            if(e->rev->w==0||dis[e->v]<t) 
                continue; 
            dis[e->v]=dis[x]+1; 
            ++gap[dis[e->v]]; 
            q.push(e->v); 
        } 
    } 

int ISAP() 

    memset(dis,0,sizeof(dis)); 
    memset(gap,0,sizeof(gap)); 
    //bfs(); 
    int ans=0,u=s,d;
    while(dis[s]<=t) 
    { 
        if(u==t) 
        { 
            int minflow=-1u>>1; 
            for(e=path[u];u!=s;e=path[u=pre[u]]) 
                minflow=min(minflow,e->w); 
            for(e=path[u=t];u!=s;e=path[u=pre[u]]) 
            { 
                e->w-=minflow; 
                e->rev->w+=minflow; 
                flow[pre[u]][u]+=minflow; 
                flow[u][pre[u]]-=minflow; 
            } 
            ans+=minflow; 
        }        
        for(e=adj[u];e;e=e->next) 
            if(e->w>0&&dis[u]==dis[e->v]+1) 
                break; 
   if(e) 
   { 
    pre[e->v]=u; 
    path[e->v]=e; 
    u=e->v; 
   } 
   else 
   { 
    if(--gap[dis[u]]==0) 
     break; 
    for(d=t,e=adj[u];e;e=e->next) 
     if(e->w>0) 
      d=min(d,dis[e->v]); 
     dis[u]=d+1; 
     ++gap[dis[u]]; 
     if(u!=s) 
      u=pre[u]; 
   } 
    } 
    return ans; 
}
int main()
{
 int i,j;
 int sum;
 int temp;
 while(scanf("%d%d",&n,&m)!=EOF)
 {
  sum=0;
  memset(adj,0,sizeof(adj));//这句要记得加哦。。
  for(i=1;i<=n;i++)
   for(j=1;j<=m;j++)
   {
    scanf("%d",&temp);
                if ((i+j)%2==0)
                    insert(0,(i-1)*m+j,temp);//坐标和为偶数的点和源点0相连
                else
                    insert((i-1)*m+j,n*m+1,temp);//坐标和为奇数数的点和汇点n*m+1相连
                sum+=temp;
   } 
   for(i=1;i<=n;i++)
    for(j=1;j<=m;j++)
     if((i+j)%2==0)
     {
      for(int k=0;k<4;k++)
      {
       int a=i+move[k][0];
       int b=j+move[k][1];
       if (a>=1&&a<=n&&b>=1&&b<=m)
       {
        insert((i-1)*m+j,(a-1)*m+b,INF);
       }
      }
     }
     s=0,t=n*m+1;
     printf("%d\n",sum-ISAP());
     
 } 
 return 0;
}

posted on 2011-08-16 19:32  →木头←  阅读(521)  评论(0编辑  收藏  举报