您的位置:首页 > 理论基础 > 计算机网络

HDU 1569 方格取数(2) 网络流的应用

2011-08-16 19:32 459 查看
//这道题就是方格取数(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
,pre
,gap
,flow

;

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
,*path
,*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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: