HDU 1569(二分图+最大流)

 

 

根据题目意思 很容易得到一个二分的概念 即只要确定了一个格子 就有能再取的格子和不能再取的格子 2种情况 可以把图化作二分图 相当于在能取的部分再取然后求取的和最大  引入最大流的概念 首先对图进行黑白染色(我们现在设i+j为奇数为黑) 然后连接所有黑的格子旁的白格子 将所有白格子连入虚拟的汇点 将所有黑格子连入虚拟的源点 用数的总和扣去求出的结果(即总和-最大流)

 

代码如下:

#include <iostream>
using namespace std;

const long maxn=3000;
const long maxm=1000000;
const long inf=0x7fffffff;

struct node
{
    
long v,next;
    
long val;
}s[maxm
*2];

long level[maxn],p[maxn],que[maxn],out[maxn],ind;

void init()
{
    ind
=0;
    memset(p,
-1,sizeof(p));
}

inline 
void insert(long x,long y,long z)
{
    s[ind].v
=y;
    s[ind].val
=z;
    s[ind].next
=p[x];
    p[x]
=ind++;
    s[ind].v
=x;
    s[ind].val
=0;
    s[ind].next
=p[y];
    p[y]
=ind++;
}


long max_flow(long n,long source,long sink)
{
    
long ret=0;
    
long h=0,r=0;
    
while(1)
    {
        
long i;
        
for(i=0;i<n;++i)
            level[i]
=0;
        h
=0,r=0;
        level[source]
=1;
        que[
0]=source;
        
while(h<=r)
        {
            
long t=que[h++];
            
for(i=p[t];i!=-1;i=s[i].next)
            {
                
if(s[i].val&&level[s[i].v]==0)
                {
                    level[s[i].v]
=level[t]+1;
                    que[
++r]=s[i].v;
                }
            }
        }
        
if(level[sink]==0)break;
        
for(i=0;i<n;++i)out[i]=p[i];
        
long q=-1;
        
while(1)
        {
            
if(q<0)
            {
                
long cur=out[source];
                
for(;cur!=-1;cur=s[cur].next)
                {
                    
if(s[cur].val&&out[s[cur].v]!=-1&&level[s[cur].v]==2)
                    {
                        
break;
                    }
                }
                
if(cur>=0)
                {
                    que[
++q]=cur;
                    
out[source]=s[cur].next;
                }
                
else
                {
                    
break;
                }
            }
            
long u=s[que[q]].v;
            
if(u==sink)
            {
                
long dd=inf;
                
long index=-1;
                
for(i=0;i<=q;i++)
                {
                    
if(dd>s[que[i]].val)
                    {
                        dd
=s[que[i]].val;
                        index
=i;
                    }
                }
                ret
+=dd;
                
for(i=0;i<=q;i++)
                {
                    s[que[i]].val
-=dd;
                    s[que[i]
^1].val+=dd;    
                }
                
for(i=0;i<=q;i++)
                {
                    
if(s[que[i]].val==0)
                    {
                        q
=index-1;
                        
break;
                    }
                }
            }
            
else
            {
                
long cur=out[u];
                
for(;cur!=-1;cur=s[cur].next)
                {
                    
if(s[cur].val&&out[s[cur].v]!=-1&&level[u]+1==level[s[cur].v])
                    {
                        
break;
                    }
                }
                
if(cur!=-1)
                {
                    que[
++q]=cur;
                    
out[u]=s[cur].next;
                }
                
else
                {
                    
out[u]=-1;
                    q
--;
                }
            }
        }
    }
    
return ret;
}


long Map[60][60];

int main()
{
    
long m,n;
    
while (scanf("%ld%ld",&m,&n)!=EOF)
    {
        init();
        
long i,j;
        
long Start=0;
        
long End=1;
        
long sum=0;

        
for (i=0;i<m;++i)
        {
            
for (j=0;j<n;++j)
            {
                scanf(
"%ld",&Map[i][j]);

                sum
+=Map[i][j];
                
                
long from,to;

                from
=i*n+j+2;

                
if ((i+j)&1)
                {
                    insert(Start,from,Map[i][j]);

                    
if (i>0)
                    {
                        to
=(i-1)*n+j+2;
                        insert(from,to,Map[i][j]);
                    }

                    
if (j>0)
                    {
                        to
=i*n+j-1+2;
                        insert(from,to,Map[i][j]);
                    }

                    
if (i<m-1)
                    {
                        to
=(i+1)*n+j+2;
                        insert(from,to,Map[i][j]);
                    }

                    
if (j<n-1)
                    {
                        to
=i*n+j+1+2;
                        insert(from,to,Map[i][j]);
                    }
                }
                
else
                {
                    insert(from,End,Map[i][j]);
                }

            }
        }

        printf(
"%ld\n",sum-max_flow(m*n+2,Start,End));


    }
    
return 0;
}
posted @ 2008-09-06 16:21  Hdu-Lost  阅读(629)  评论(0编辑  收藏  举报