列表

详情


NC225285. 牛牛防疫情

描述

牛牛用卖烤串赚的钱买了一款游戏,这款游戏的地图是一个 n*n 的网格,其中有 m 个地区存在感染源(红色),其余地区为安全区(白色)。已知一个感染源可同时将与其相邻(上下左右)的安全区感染,被感染的安全区称之为新发地(黄色)。一个安全区变为一个新发地需要付出大小为 c 的代价。新发地可在下一时刻作为感染源将与其相邻的安全区感染为新的新发地。
为了遏制疫情扩散,牛牛决定采取下列两种措施
1. 在感染源(新发地)周围修建墙,墙可阻止疫情的扩散。但每堵墙需要付出大小为 1 的代价。
2. 任意让疫情扩散。

牛牛现在想知道采取哪种措施可以使得付出的代价最小。

输入描述

第一行三个整数 n,m,c
第2至 m+1 行,每行两个整数x、y,代表感染源的位置坐标(x,y)

输出描述

一个正整数,表示最小代价的值

示例1

输入:

6 2 2
2 0
3 1

输出:

7

示例2

输入:

6 8 3
1 1
1 2
1 3
2 1
2 3
3 1
3 2
3 3

输出:

15

说明:

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++ 解法, 执行用时: 51ms, 内存消耗: 6528K, 提交时间: 2021-09-27 16:11:21

#include<bits/stdc++.h>
using namespace std;
const int N=205*205;
const int M=N*6;
int n,m,c,x,y,z,tot=1,num,s,t,ans,last[N],d[N],co[N],cur[N],fx[4][2]={0,1,0,-1,1,0,-1,0};
bool bz[205][205];
struct cost
{
	int to,nex,flow;
}e[M+M];
int min(int a,int b){return a<b?a:b;}
int get(int x,int y)
{
	return (x-1)*n+y;
}
void add(int x,int y,int z)
{
	e[++tot]=(cost){y,last[x],z},last[x]=tot;
	e[++tot]=(cost){x,last[y],0},last[y]=tot;
}
int DFS(int x,int y)
{
	if (x==t) return y;
	int u=0,p;
	for (int i=cur[x];i;i=e[i].nex)
	{
		cur[x]=i;
		if (e[i].flow>0 && d[e[i].to]+1==d[x])
		{
			p=DFS(e[i].to,min(e[i].flow,y-u));
			u+=p,e[i].flow-=p,e[i^1].flow+=p;
			if (u==y) return u;
		}
	}
	cur[x]=last[x];
	if (!(--co[d[x]])) d[s]=num;
	++co[++d[x]];
	return u;
}
int main()
{
	cin>>n>>m>>c;
	for (int i=1;i<=m;i++) cin>>x>>y,bz[x+1][y+1]=1;
	s=n*n+1,t=s+1;
	for (int i=1;i<=n;i++)
		for (int j=1;j<=n;j++)
		{
			for (int k=0;k<4;k++)
			{
				x=i+fx[k][0],y=j+fx[k][1];
				if (!x || x>n || !y || y>n) continue;
				add(get(i,j),get(x,y),1);
			}
			if (bz[i][j]) add(s,get(i,j),1<<30);
			add(get(i,j),t,c);
		}
	num=t;
	co[0]=num;
	ans=-m*c;
	for (;d[s]<num;) ans+=DFS(s,1<<30);
	cout<<ans<<endl;
	return 0;
}

上一题