【BZOJ-1324】Exca王者之剑 最小割

时间:2023-03-08 18:42:45

1324: Exca王者之剑

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 483  Solved: 248
[Submit][Status][Discuss]

Description

【BZOJ-1324】Exca王者之剑         最小割 【BZOJ-1324】Exca王者之剑         最小割

Input

第一行给出数字N,M代表行列数.N,M均小于等于100 下面N行M列用于描述数字矩阵

Output

输出最多可以拿到多少块宝石

Sample Input

2 2
1 2
2 1

Sample Output

4

HINT

Source

2007Amber国家队论文

Solution

最小割裸模型

见棋盘直接黑白染色,偶数秒发生消失?那就偶数秒和奇数秒分开二分图建图即可

Code

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int read()
{
int x=,f=; char ch=getchar();
while (ch<'' || ch>'') {if (ch=='-') f=-; ch=getchar();}
while (ch>='' && ch<='') {x=x*+ch-''; ch=getchar();}
return x*f;
}
#define maxm 1000010
#define maxn 10010
int n,m,tot;
struct EdgeNode{int next,to,cap;}edge[maxm];
int head[maxn],cnt=;
void add(int u,int v,int w)
{
cnt++;
edge[cnt].next=head[u]; head[u]=cnt; edge[cnt].cap=w; edge[cnt].to=v;
}
void insert(int u,int v,int w) {add(u,v,w); add(v,u,);} int val[][]; int dis[maxn],que[maxn<<],cur[maxn],S,T;
bool bfs()
{
for (int i=S; i<=T; i++) dis[i]=-;
que[]=S; dis[S]=; int he=,ta=;
while (he<ta)
{
int now=que[he++];
for (int i=head[now]; i; i=edge[i].next)
if (edge[i].cap && dis[edge[i].to]==-)
dis[edge[i].to]=dis[now]+,que[ta++]=edge[i].to;
}
return dis[T]!=-;
}
int dfs(int loc,int low)
{
if (loc==T) return low;
int w,used=;
for (int i=cur[loc]; i; i=edge[i].next)
if (edge[i].cap && dis[edge[i].to]==dis[loc]+)
{
w=dfs(edge[i].to,min(low-used,edge[i].cap));
edge[i].cap-=w; edge[i^].cap+=w;
used+=w; if (edge[i].cap) cur[loc]=i;
if (used==low) return low;
}
if (!used) dis[loc]=-;
return used;
}
#define inf 0x7fffffff
int dinic()
{
int tmp=;
while (bfs())
{
for (int i=S; i<=T; i++) cur[i]=head[i];
tmp+=dfs(S,inf);
}
return tmp;
}
int locate(int x,int y) {return (x-)*m+y;}
int main()
{
n=read(),m=read();
for (int i=; i<=n; i++)
for (int j=; j<=m; j++)
val[i][j]=read(),tot+=val[i][j];
S=,T=n*m+;
for (int i=; i<=n; i++)
for (int j=; j<=m; j++)
if ((i+j)%==)
{
insert(S,locate(i,j),val[i][j]);
if (i+<=n) insert(locate(i,j),locate(i+,j),inf);
if (i->=) insert(locate(i,j),locate(i-,j),inf);
if (j+<=m) insert(locate(i,j),locate(i,j+),inf);
if (j->=) insert(locate(i,j),locate(i,j-),inf);
}
else insert(locate(i,j),T,val[i][j]);
int maxflow=dinic();
printf("%d\n",tot-maxflow);
return ;
}

微机课随随便便打着玩系列,被旁边同学摁了个数,然后第一遍还WA了...纸张