Description
Input
Output
Sample Input
Input 1
3 3 1
0 1 0
2 0 1
0 1 0
1 3
Input 2
3 3 4
0 2 0
0 0 4
0 3 0
1 3
2 1
2 2
3 1
Sample Output
Output 1
3
Output 2
9
Data Constraint
分析:
今天模拟赛,出题人做了自己出的题目……
出题人表示看到题目非常尴尬,然后ak了。
设
x
+
y
x+y
x+y为奇数的为黑点,否则为白点。
显然我们选一个黑点,就要在上下两个中选一个白点和一个在左右两个中选一个白点。
那么就可以给费用流建模了。我们把横坐标为偶数的白点放在左边,横坐标为奇数的放右边。黑点分成两个点,这两个点连一条费用为
v
(
x
,
y
)
v_{(x,y)}
v(x,y)的边,横坐标为偶数的白点点连左边的黑点,右边的黑点连横坐标为奇数的白点,然后连上源汇就好了。显然一次只会加
1
1
1点流量,所以当跑了
m
m
m次,或最长路为负即可退出(显然不一定要加上所有的点)。
考场上一直在想怎样一次流掉这两个点,一直把这个放在一边,然后就想不出来了。
代码:
/**************************************************************
Problem: 5403
User: liangzihao
Language: C++
Result: Accepted
Time:1264 ms
Memory:3872 kb
****************************************************************/
#include <iostream>
#include <cstdio>
#include <cmath>
#include <queue>
const int maxn=1e4+7;
const int maxe=1e5+7;
const int inf=0x3f3f3f3f;
using namespace std;
int n,m,k,x,ans,cnt,s,t,y;
int ls[maxn],dis[maxn],vis[maxn],pre[maxn],a[100][100],b[maxn];
queue <int> q;
struct edge{
int x,y,w,c,op,next;
}g[maxe];
void add(int x,int y,int w,int c)
{
g[++cnt]=(edge){x,y,w,c,cnt+1,ls[x]};
ls[x]=cnt;
g[++cnt]=(edge){y,x,0,-c,cnt-1,ls[y]};
ls[y]=cnt;
}
int po(int x,int y)
{
return (x-1)*n+y;
}
bool spfa()
{
while (!q.empty()) q.pop();
for (int i=s;i<=t;i++)
{
dis[i]=-inf;
vis[i]=0;
}
dis[s]=0;
q.push(s);
vis[s]=1;
while (!q.empty())
{
int x=q.front();
q.pop();
for (int i=ls[x];i>0;i=g[i].next)
{
int y=g[i].y;
if ((g[i].w) && (dis[y]<dis[x]+g[i].c))
{
dis[y]=dis[x]+g[i].c;
pre[y]=i;
if (!vis[y])
{
vis[y]=1;
q.push(y);
}
}
}
vis[x]=0;
}
if (dis[t]>0) return 1;
return 0;
}
void mcf()
{
int i=t,x=1e9;
while (i!=s)
{
x=min(x,g[pre[i]].w);
i=g[pre[i]].x;
}
i=t;
while (i!=s)
{
g[pre[i]].w-=x;
g[g[pre[i]].op].w+=x;
ans-=g[pre[i]].c*x;
i=g[pre[i]].x;
}
}
int main()
{
scanf("%d%d%d",&n,&m,&k);
s=0; t=n*n*2+1;
for (int i=1;i<=n;i++)
{
for (int j=1;j<=n;j++)
{
scanf("%d",&a[i][j]);
}
}
for (int i=1;i<=k;i++)
{
scanf("%d%d",&x,&y);
b[po(x,y)]=1;
}
for (int i=1;i<=n;i++)
{
for (int j=1;j<=n;j++)
{
ans+=a[i][j];
if (b[po(i,j)]) continue;
if ((i+j)%2==0)
{
if (i%2==0)
{
add(s,po(i,j),1,0);
if (i>1) add(po(i,j),po(i-1,j),1,0);
if (j>1) add(po(i,j),po(i,j-1),1,0);
if (i<n) add(po(i,j),po(i+1,j),1,0);
if (j<n) add(po(i,j),po(i,j+1),1,0);
}
else
{
add(po(i,j),t,1,0);
if (i>1) add(n*n+po(i-1,j),po(i,j),1,0);
if (j>1) add(n*n+po(i,j-1),po(i,j),1,0);
if (i<n) add(n*n+po(i+1,j),po(i,j),1,0);
if (j<n) add(n*n+po(i,j+1),po(i,j),1,0);
}
}
else
{
add(po(i,j),n*n+po(i,j),1,a[i][j]);
}
}
}
for (int i=1;i<=m;i++)
{
if (spfa()) mcf();
}
printf("%d",ans);
}