joj 2656: 霍格瓦兹魔法阵 最小割
2011-09-20 20:00
225 查看
最近,伏地魔开始网罗党羽, 许多女巫和男巫为了获得他赋予的力量加入了他的阵营。为了抵抗伏地魔的进攻,霍格瓦兹的魔法师们摆出了一个 n * m 方格的魔法方阵,每个方格中都站有一位魔法师。 当然,魔法师们都有自己的魔法值,用非负整数表示。 然而,对伏地魔发起攻击时,为了安全起见,任意两个相邻的魔法师 (上下相邻或左右相邻) 不能同时施展魔法。为了打败强大的伏地魔,你能帮助霍格瓦兹的魔法师们找出最大可能的攻击魔法值么?
输入含有多组case 每个case的第一行有两个整数 n 和 m ,代表魔法方阵的规模 接下来输入的是 n * m 的非负整数矩阵。 n和m均不超过50 当n=m=0时,输入结束
对每个case, 输出最大可能魔法值
//
#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
;
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
,cur
,dis
,gap
;
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;
}
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
;
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
,cur
,dis
,gap
;
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;
}
相关文章推荐
- JOJ 2656: 霍格瓦兹魔法阵 //最小割
- JOJ 1170 :Wire Is So Expensive 最小生成树
- CJOJ 2484 函数最小值 / Luogu 2085 函数最小值
- joj 2724: Hua Rong Dao 最小割
- CJOJ 2427 最小生成树
- joj 2672 Hanoi Tower Once More 有向无环图的最小路径覆盖=N-最大匹配
- JOJ 2724 hua rong dao (最小割 拆点)[无代码]
- zoj 1450 Minimal Circle(最小覆盖圆)
- HDU 1151 Air Raid 二分图的最小路径覆盖
- hdu 4463 最小生成树 prim
- 华为OJ(输出数组最小k个数)
- hdu 1102(最小生成树)
- Prim算法求图的最小生成树--C代码
- F - Jungle Roads(最小生成树)
- 最小圆覆盖(经典算法【三点定圆)
- joj 2737 狼与羊的故事 求任意两点之间的必经之路
- sql 选出所有人的最小成绩
- HDU 3371 最小生成树 kruskal
- HDU 4289 Control (最小割 拆点)
- 图论笔记-最短路+二分图最大匹配+最小路径覆盖