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;
}
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;
}