To_Heart—题解——P6234 [eJOI2019] T形覆盖

news/2024/7/15 19:16:11 标签: 图论, 算法, 深度优先

link.

突然很想写这篇题解。虽然题目不算难。

考场只有30分是为什么呢?看来是我没有完全理解这道题目吧!

首先很明显的转换是,把 T 型覆盖看成十字形,再考虑最后减去某一块的贡献。

然后然后直接往原图上面放十字形!对于每一个十字的中心来说,实际上它只需要三个相邻的方块就可以了。而我们发现两个十字重合的部分不会超过两个方块,也就是说把这两个方块任意分配给两个人,就能保证这两个每个人都只会舍弃一个方块。

因为每次两个十字的重合最多只能让每个点丢弃一个方块,并且每次重合至少有一个十字会丢弃掉一个方块,所以惊天的结论是我们可以直接计算整个十字连通块的中心点和非中心点的个数。如果非中心点的个数大于等于中心点的个数的三倍,那么当前连通块一定合法,否则不能保证每个十字的中心点都能分配到刚好三个非中心点,即无解。

但是可能有非中心点的个数大于中心点的个数的三倍。这种情况说明所有的十字都只重合了一个点,那么必须要丢掉一个非中心点。因为要权值最大所以丢掉最小权值的就好了。

其实这个的实现方式有很多,但是我使用了并查集。为什么呢?因为其他题解就是用的并查集啊!

然后并查集需要注意的点就是不能选择中心点啊。中心点的权值设为最大值好不好。

#include<bits/stdc++.h>
using namespace std;

int n,m,k;
int a[1000005];
int ID(int x,int y){
	return (x-1)*m+y;
}
int pre[1000005],dp[1000005];
int sz[1000005][2];
long long sum[1000005];

bool vis[1000005];

struct zz{
	int x,y;
}t[1000005];

int Find(int x){
	if(pre[x]!=x) pre[x]=Find(pre[x]);
	return pre[x];
}
void Join(int x,int y){
	int fx=Find(x),fy=Find(y);
	if(fx==fy) return ;
	pre[fy]=fx,sum[fx]+=sum[fy],dp[fx]=min(dp[fx],dp[fy]),sz[fx][0]+=sz[fy][0],sz[fx][1]+=sz[fy][1];
}

int fx[5]={0,1,-1,0,0};
int fy[5]={0,0,0,1,-1};

int main(){
//	freopen("t-covering.in","r",stdin);
//	freopen("t-covering.out","w",stdout);
	cin>>n>>m;
	for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) scanf("%d",&a[ID(i,j)]);
	cin>>k;
	for(int i=1,x,y;i<=k;i++) scanf("%d%d",&x,&y),t[i]=(zz){x+1,y+1};
	for(int i=1;i<=k;i++) vis[ID(t[i].x,t[i].y)]=1;
	for(int i=1;i<=n*m;i++){
		pre[i]=i,sum[i]=a[i],dp[i]=a[i],sz[i][vis[i]]=1;
		if(vis[i]) dp[i]=0x3f3f3f3f; 
	}
	for(int i=1;i<=k;i++) for(int j=1;j<=4;j++){
		int x=t[i].x,y=t[i].y;int dx=x+fx[j],dy=y+fy[j];
		if(dx<=0||dx>n||dy<=0||dy>m) continue;
		Join(ID(x,y),ID(dx,dy)); 
	}
	long long ans=0;
	memset(vis,0,sizeof vis);
	for(int i=1;i<=n;i++) for(int j=1;j<=m;j++){
		int x=(ID(i,j));int fx=Find(x);
		if(vis[fx]) continue; vis[fx]=1;
		if(sz[fx][0]<sz[fx][1]*3) return printf("No\n"),0;
        else if(sz[fx][0]==sz[fx][1]*3) ans+=sum[fx];
        else ans+=sum[fx]-dp[fx];
	}
	cout<<ans<<endl;
	return 0;
}

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

相关文章

朴实无华的数据增强然后训练一下应用在电网异物检测领域,好像有自己的数据集就能发文了

RCNN-based foreign object detection for securing power transmission lines (RCNN4SPTL) Abstract 本文提出了一种新的深度学习网络——RCNN4SPTL (RCNN -based Foreign Object Detection for Securing Power Transmission lines)&#xff0c;该网络适用于检测输电线路上的…

taro h5 formData上传图片的坑-Required request part ‘file‘ is not present

描述&#xff1a;用formData上传图片 1、生成formData const formData new FormData() formData.append(file, data) // data是file formData.append(xxx, xxx) // 添加其他参数2、用taro.request请求 Taro.request({url: xxxx,data: formData,header: {Content-Type: mult…

Asyncio support

Python 3.4及更高版本中内置的asyncio模块可用于在单个线程中编写异步代码。此库支持使用can.Notifier类在事件循环中异步接收消息。 每个CAN总线仍将有一个线程,但用户应用程序将完全在事件循环中执行,从而实现更简单的并发性,而无需担心线程问题。但是,具有有效文件描述…

SRM系统招投标管理:提升供应链效能

在现代商业环境中&#xff0c;供应链管理的成功与否对企业的运作效率和竞争力有着至关重要的影响。而招投标管理作为供应链管理的重要环节之一&#xff0c;其有效性和高效性对于企业的成功非常关键。为了提升招投标管理的效率和质量&#xff0c;越来越多的企业开始采用供应关系…

huggingface datasets离线加载文件的解决方案

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…

vue3 + vuedraggable: ^4.1.0 实现列表拖拽

这个案例是利用vuedraggable渲染动态组件&#xff0c; bug&#xff1a;拖拽失效 vue2是需要在component这个标签上v-for&#xff0c;vue3是不需要的 <template><div><div><vuedraggableref"drag"v-model"state.listComp"v-bind&qu…

纯js封装一个弹出窗口

先上效果图&#xff1a; 左图是默认的样式(默认标题是黑色的。不是橙色的。截图时我改了点东西所以变了色。。。)。右图是通过传递参数自定义了外观的样式。 封装实现&#xff1a; function showWindow() {this.rnd Math.random();this.obj null;this.title ;this.content …

使用Pandas处理Excel文件

Excel工作表是非常本能和用户友好的&#xff0c;这使得它们非常适合操作大型数据集&#xff0c;即使是技术人员也不例外。如果您正在寻找学习使用Python在Excel文件中操作和自动化内容的地方&#xff0c;请不要再找了。你来对地方了。 在本文中&#xff0c;您将学习如何使用Pan…