【GDKOI2010】圈地计划

news/2024/7/15 17:28:18 标签: 图论, 算法

题目大意

给定一个 n ∗ m n*m nm 的矩阵,每个点可以选择 0 0 0 1 1 1 ,给定数组 A i , j A_{i,j} Ai,j 和数组 B i , j B_{i,j} Bi,j ,表示点 ( i , j ) (i,j) (i,j) 选择 0 0 0 获得 A i , j A_{i,j} Ai,j 的价值,否则获得 B i , j B_{i,j} Bi,j 的价值。
再给定数组 C i , j C_{i,j} Ci,j 表示与 ( i , j ) (i,j) (i,j) 相邻(即点 ( i − 1 , j ) , ( i , j − 1 ) , ( i + 1 , j ) , ( i , j + 1 ) (i-1,j),(i,j-1),(i+1,j),(i,j+1) (i1,j),(i,j1),(i+1,j),(i,j+1)) 且与 ( i , j ) (i,j) (i,j) 选择一样时的附加价值,若有 k k k 个点相邻,则增加贡献为 k ∗ C i , j k*C_{i,j} kCi,j ,求最大的价值。

Input & Output

输入:第一行 n , m n,m n,m ,接下来三个 n ∗ m n*m nm 的矩阵分别表示矩阵 A , B , C A,B,C A,B,C
输出:一个整数,即最大价值。

数据范围

n , m ≤ 100 , 0 ≤ A i , j , B i , j , C i , j ≤ 1000 n,m \le 100,0 \le A_{i,j},B_{i,j},C_{i,j} \le 1000 n,m100,0Ai,j,Bi,j,Ci,j1000

思路

我们可以将题目看作:给定 n ∗ m n*m nm 个点,每个点可以选择 0 0 0 1 1 1 ,二者必须选一个,其中点之间若选相同的就有附加价值,求最大价值。
考虑到每一个点能且只能选一个,根据最小割的定义(最小代价使得图被割为两部分),可以根据总价值 − - 最小割(最大流) = = = 最大价值进行求解。
问题在于建图。矩阵 A A A B B B 建图并不难,源点连向各个点赋为 A A A 的值,表示若不选 A A A 的代价,汇点同理,难点在于点与点之间的连边。
这涉及到了一种网络流模型:二元关系网络流
讲地详细的大佬博客:网络流二元关系 。
我们只需要在有价值之间的点分别连两条双向边就可以了。
之后就成为网络流版题了。

AC代码

#include<cstring>
#include<iostream>
#include<cstdio>
#include<algorithm>
#define INF 21000000
using namespace std;
long long n,m,s,t,cnt,sum,dep[400200],to[400200],nxt[400200],flo[400200];
int head[400200],hed[400200];
long long A[220][220],B[220][220],C[220][220],dian[220][220],nod,f[400400];
void xx(int u,int v,long long w)
{
	cnt++;
	to[cnt]=v;
	flo[cnt]=w;
	nxt[cnt]=head[u];
	head[u]=cnt;
	cnt++;
}
void pd(int a1,int a2,int b1,int b2,long long va)
{
	if(!dian[a1][a2]||!dian[b1][b2])
	return;
	xx(dian[a1][a2],dian[b1][b2],va);
	xx(dian[b1][b2],dian[a1][a2],0);
}
bool bfs()
{
	memset(dep,-1,sizeof(dep));
	memcpy(hed,head,sizeof(head));
	int he=0,ta=1;
	dep[s]=1;
	f[1]=s;
	
	while(he<ta)
	{
		he++;
		int x=f[he];
		for(int i=head[x];i!=-1;i=nxt[i])
		{
			int y=to[i];
//			printf("%d %d %d %d\n",he,x,y,i);
			if(dep[y]==-1&&flo[i])
			{
				dep[y]=dep[x]+1;
				ta++;
				f[ta]=y;
			}
		}
	}
	return dep[t]!=-1;
}
long long dfs(int x,long long flow)
{
//	printf("%d %lld\n",x,flow);
	if(x==t) return flow;
	long long now=flow;
	for(int i=hed[x];i!=-1;i=nxt[i])
	{
		hed[x]=i;
		int y=to[i];
		if(dep[y]==dep[x]+1&&flo[i])
		{
			
		    long long d=dfs(y,min(now,flo[i]));
		    flo[i]-=d,flo[i^1]+=d;
		    now-=d;
		    if(now==0)
		    break;
		}
	}
	return flow-now;
}
long long dinic()
{
	long long ans=0;
	while(bfs())
	ans+=dfs(s,INF);
	return ans; 
}
int main()
{
	memset(head,-1,sizeof(head));
    scanf("%d %d",&n,&m);
    s=0,t=n*m+1;
    for(int i=1;i<=n;i++)
     for(int j=1;j<=m;j++)
     nod++,dian[i][j]=nod;
	for(int i=1;i<=n;i++)
	 for(int j=1;j<=m;j++)
	 scanf("%lld",&A[i][j]),sum+=A[i][j],xx(s,dian[i][j],A[i][j]),xx(dian[i][j],s,0);
	for(int i=1;i<=n;i++)
	 for(int j=1;j<=m;j++)
	 scanf("%lld",&B[i][j]),sum+=B[i][j],xx(dian[i][j],t,B[i][j]),xx(t,dian[i][j],0);
	for(int i=1;i<=n;i++)
	 for(int j=1;j<=m;j++)
	 {
	 	scanf("%lld",&C[i][j]);
	 	if(i-1>0)
	 	sum=(sum+C[i][j]+C[i-1][j]);
	 	if(j-1>0)
	 	sum=(sum+C[i][j]+C[i][j-1]);
	 }
	for(int i=1;i<=n;i++)
	 for(int j=1;j<=m;j++)
	 {
	 	pd(i,j,i-1,j,C[i][j]+C[i-1][j]);
	 	pd(i,j,i,j-1,C[i][j]+C[i][j-1]);
	 	pd(i,j,i+1,j,C[i][j]+C[i+1][j]);
	 	pd(i,j,i,j+1,C[i][j]+C[i][j+1]);
	 }
	 printf("%lld\n",sum-dinic());

http://www.niftyadmin.cn/n/1318780.html

相关文章

web.xml之Spring配置(基于Spring+Struts+Ibatis)

指定Spring配置文件位置 <context-param><param-name>contextConfigLocation</param-name><param-value>/WEB-INF/spring-dao-bean.xml,/WEB-INF/spring-resources.xml,/WEB-INF/spring-service-bean.xml</param-value> </context-param> …

【GDKOI2010】推箱子

题目大意 给定 nnn 个矩形&#xff0c;每条边都平行与坐标轴的一条边&#xff0c;分别有 444 个量 xi,yi,Lxi,Lyix_{i},y_{i},Lx_{i},Ly_{i}xi​,yi​,Lxi​,Lyi​ &#xff0c;xi,yix_{i},y_{i}xi​,yi​ 表示矩形左下角的点的坐标&#xff0c;Lxi,LyiLx_{i},Ly_{i}Lxi​,Lyi…

JUnit使用的设计模式

JUnit源代码涉及使用了大量设计模式 1、模板方法模式&#xff08;Template Method&#xff09; 定义一个操作中的算法骨架&#xff0c;而将一些步骤延伸到子类中去&#xff0c;使得子类可以不改变一个算法的结构&#xff0c;即可重新定义该算法的某些特定步骤。这里需要复用的是…

经理怎么和员工搞好关系和信任

产品经理应该有坚实的专业基础&#xff0c;这里的基础包括产品方向和产品策略的把握&#xff0c;包括设计&#xff0c;也包括对技术的理解和见识&#xff0c;对运营和市场的敏感&#xff0c;以及良好的沟通和协作能力。换言之&#xff0c;既然是产品经理&#xff0c;整个产品的…

计算几何专题笔记

1.向量 1.1向量加减法 (x1,y1)→(x2,y2)→(x1x2,y1y2)→\overrightarrow{(x_{1},y_{1})} \overrightarrow{(x_{2},y_{2})} \overrightarrow{(x_{1}x_{2},y_{1}y_{2})}(x1​,y1​)​(x2​,y2​)​(x1​x2​,y1​y2​)​。 (x1,y1)→−(x2,y2)→(x1−x2,y1−y2)→\overrightarro…

python byte array

这两天在用python处理string时&#xff0c;需要对string做加密处理。加密的算法就是依次对string以字节为单位做运算&#xff08;不说细节了&#xff09;。 如果string由ascii码组成&#xff0c;直接遍历string计算就可以了。但如果string包含非ascii字符&#xff0c;就不适用了…

如何带好自已的团队

在网上看到博客"怎么才能让团队成员好好干活"的评论&#xff0c;觉得写的比较好。原文如下&#xff1a;我做团队管理有几年了吧&#xff0c;我和你分享一下我认为带好团队的几点&#xff1a;1.诚信对团队内成员&#xff0c;无论是技术研究、交流、问题探讨&#xff0…

智能手机使用小常识

智能手机使用小常识 智能手机使用小常识 如何快速掌握智能手机小常识&#xff0c;下面我们写个小案例分析一下&#xff0c;数据模式在没用的时候可以关闭&#xff0c;可以省去很多的流量。 1数据模式 在使用的时候再打开&#xff0c;不然&#xff0c;很多软件会耗光你的流量&am…