题目大意:给你一个N*N的棋盘,棋盘上每个点都有一个权值

第一问求一个权值形成的最大联通块中点的数量

第一问求两个权值共同形成的最大联通块中点的数量

提供一种并查集的做法:(感谢大佬们的题解)
第一问把所有相同权值的相邻的点用带权并查集合并一下就OK了

第二问,就需要一些骚操作了

我们的目的是把两个不同权值的所有联通块合并,再去看它们共同形成的最大联通块的大小

可以用一个结构体记录两个联通块之间的关系

分别是两个联通块的标号(即这个联通块构成的并查集的祖先节点)

以及这两个联通块的颜色

而为了简化后面的匹配过程,要把第一个块的颜色编号改成较小的,第二个块的颜色编号改成较大的

然后对这个结构体按颜色编号的首项排序,如果首项相同就按第二项排序

这么做的目的是,让 两个相同颜色的联通块之间的关系 形成一段连续的区间,这样我们就可以省去很多时间!!!

然后每次都按关系从前到后 去合并两个颜色,统计答案,再用几个数组把并查集还原回去就行了;

 #include <cstdio>
#include <algorithm>
#include <cstring>
#define N 255
#define maxn 1000010
using namespace std; int n,cnt;
int a[N][N],fa[N*N],id[N][N],use[N*N],que[N*N],sum[N*N],sm[N*N];
struct E{
int x,y,c1,c2;
}e[N*N*];
int cmp(E s1,E s2)
{
if(s1.c1!=s2.c1) return s1.c1<s2.c1;
else return s1.c2<s2.c2;
} void e_add(int xx,int yy,int cc1,int cc2)
{
cnt++;
if(cc1>cc2) swap(cc1,cc2),swap(xx,yy);
e[cnt].x=xx,e[cnt].c1=cc1;
e[cnt].y=yy,e[cnt].c2=cc2;
}
bool check(int x,int y)
{
if(x<||y<||x>n||y>n) return false;
else return true;
}
int find_fa(int x)
{
int fx=x;
while(fx!=fa[fx]) fx=fa[fx];
while(x!=fx){
int pre=fa[x];
fa[x]=fx;
x=pre;
}
return x;
}
void mrg1(int x,int y)
{
x=find_fa(x),y=find_fa(y);
if(x!=y){
fa[y]=x;
sum[x]+=sum[y];
}
}
void mrg2(int x,int y)
{
x=find_fa(x),y=find_fa(y);
if(x!=y){
fa[y]=x;
sm[x]+=sm[y];
}
} int main()
{
//freopen("data.in","r",stdin);
scanf("%d",&n);
for(int i=;i<=n;i++)
for(int j=;j<=n;j++)
{
scanf("%d",&a[i][j]);
id[i][j]=(i-)*n+j;
}
for(int i=;i<=n*n;i++) sum[i]=,fa[i]=i;
for(int i=;i<=n;i++)
for(int j=;j<=n;j++)
{
if(check(i+,j)&&a[i][j]==a[i+][j])
mrg1(id[i][j],id[i+][j]);
if(check(i,j+)&&a[i][j]==a[i][j+])
mrg1(id[i][j],id[i][j+]);
}
for(int i=;i<=n*n;i++) sm[i]=sum[i];
for(int i=;i<=n;i++)
for(int j=;j<=n;j++)
{
if(check(i+,j)&&a[i][j]!=a[i+][j])
e_add(find_fa(id[i][j]),find_fa(id[i+][j]),a[i][j],a[i+][j]);
if(check(i,j+)&&a[i][j]!=a[i][j+])
e_add(find_fa(id[i][j]),find_fa(id[i][j+]),a[i][j],a[i][j+]);
}
sort(e+,e+cnt+,cmp);
int ct=,ret=;
for(int i=;i<=n*n;i++)
ret=max(ret,sum[i]);
printf("%d\n",ret);
ret=;
for(int i=;i<=cnt;i++,ct=)
{
que[++ct]=e[i].x,que[++ct]=e[i].y;
use[e[i].x]=use[e[i].y]=;
mrg2(e[i].x,e[i].y); //merge
while(e[i+].c1==e[i].c1&&e[i+].c2==e[i].c2){
i++;
if(!use[e[i].x]) use[e[i].x]=,que[++ct]=e[i].x;
if(!use[e[i].y]) use[e[i].y]=,que[++ct]=e[i].y;
mrg2(e[i].x,e[i].y);
}
for(int j=;j<=ct;j++) //calc
ret=max(ret,sm[que[j]]);
for(int j=;j<=ct;j++) //clear
{
fa[que[j]]=que[j];
sm[que[j]]=sum[que[j]];
use[que[j]]=;
}
}
printf("%d\n",ret);
return ;
}

[USACO18OPEN] Multiplayer Moo (并查集+维护并查集技巧)的更多相关文章

  1. 洛谷P4380 [USACO18OPEN]Multiplayer Moo

    题目 第一问: 用广搜类似用\(floodfill\)的方法. 第二问: 暴力枚举加剪枝,对于每个连通块,枚举跟这个连通块相连的其他与他颜色不同的连通块,然后向外扩展合并颜色与他们俩相同的连通块.扩展 ...

  2. hihoCoder #1291 : Building in Sandbox 逆向处理+并查集维护

    /** 题目:#1291 : Building in Sandbox 链接:https://hihocoder.com/problemset/problem/1291 题意:就是一个三维的空间里,按照 ...

  3. [Codeforces 1027 F] Session in BSU [并查集维护二分图匹配问题]

    题面 传送门 思路 真是一道神奇的题目呢 题目本身可以转化为二分图匹配问题,要求右半部分选择的点的最大编号最小的一组完美匹配 注意到这里左边半部分有一个性质:每个点恰好连出两条边到右半部分 那么我们可 ...

  4. Codeforces325 D【并查集维护连通性】

    参考:大牛blog 思路: 因为是环,所以可以复制一下图,先判断一下和他是不是和与他相邻的8个之一的一个障碍使得构成了一个环,环就是一个连通,用并查集维护即可: 如果没有就ans++,然后并把这个点加 ...

  5. 2019牛客暑期多校训练营(第八场)E:Explorer(LCT裸题 也可用线段树模拟并查集维护连通性)

    题意:给定N,M,然后给出M组信息(u,v,l,r),表示u到v有[l,r]范围的通行证有效.问有多少种通行证可以使得1和N连通. 思路:和bzoj魔法森林有点像,LCT维护最小生成树.  开始和队友 ...

  6. POJ2985 The k-th Largest Group[树状数组求第k大值+并查集||treap+并查集]

    The k-th Largest Group Time Limit: 2000MS   Memory Limit: 131072K Total Submissions: 8807   Accepted ...

  7. 浅谈并查集&种类并查集&带权并查集

    并查集&种类并查集&带权并查集 前言: 因为是学习记录,所以知识讲解+例题推荐+练习题解都是放在一起的qvq 目录 并查集基础知识 并查集基础题目 种类并查集知识 种类并查集题目 并查 ...

  8. KingbbaseES V8R6集群维护案例之---集群之间数据迁移

    案例说明: 生产环境是集群环境,测试环境是集群,现需要将生产环境的数据迁移到测试集群中运行,本文档详细介绍了从集群环境迁移数据的操作步骤,可以作为生产环境迁移数据的参考. 适用版本: Kingbase ...

  9. MongoDB之分片集群与复制集

    分片集群 1.1.概念 分片集群是将数据存储在多台机器上的操作,主要由查询路由mongos.分片.配置服务器组成. ●查询路由根据配置服务器上的元数据将请求分发到相应的分片上,本身不存储集群的元数据, ...

随机推荐

  1. JAVA学习之枚举

    1.新建一个枚举类 public enum Apple{ FUJI, PIPPIN, GRANNY_SMITH } 通过查看字节码,可以看到,枚举类的实现方式: 1)继承自java.lang.Enum ...

  2. [转载]解决/usr/bin/ld: cannot find -lxxx

    在linux环境编译应用程式或lib的source code时常常会出现如下的错误讯息: /usr/bin/ld: cannot find -lxxx 这些讯息会随着编译不同类型的source cod ...

  3. RE:ゼロから始める文化課生活

    觉得有必要在NOI之前开一篇学习内容记录. 至于为什么要取这个标题呢?也许并没有什么特殊的借口吧. 5.23 在LOJ上搬了三道原题给大家考了考,然后大家都在考试就我一个人在划水. SSerxhs 和 ...

  4. POJ 2132

    我早上调了一个早上,下午才发现把e=edge[e].next写成edge[e].next了... 这题直接DFS,一个剪枝是,当当前的最大质因数是最小公倍数的因数时,不用搜索 #include < ...

  5. HDOJ 5099 Comparison of Android versions 坑题

    现场赛的时候错了十四次. . ... Comparison of Android versions Time Limit: 2000/1000 MS (Java/Others)    Memory L ...

  6. R语言的帮助使用和图形功能简单介绍

    R语言的帮助使用和图形功能简单介绍 R语言帮助,在Windows桌面下,有很多种.最长使用的是在命令行下help() > help.start() 会在浏览器中,打开帮助的主页 watermar ...

  7. SSH学习之中的一个 OpenSSH基本使用

    在Linux系统中.OpenSSH是眼下最流行的远程系统登录与文件传输应用,也是传统Telenet.FTP和R系列等网络应用的换代产品. 当中,ssh(Secure Shell)能够替代telnet. ...

  8. java中super的作用

    super()的作用 super能够用来訪问超类的构造方法和被子类所隐藏的方法.假设子类中有方法与超类中的方法名称和參数同样,则超类中的方法就被隐藏起来,也就是说在子类中重载了父类中的方法. 引用父类 ...

  9. MVC发送邮件

    <> 发送邮件报错说明 发送邮件 假设发送人的邮箱username与邮箱password都没有填写错误:假设报:參数或变量中有语法错误. server响应为:mail from addre ...

  10. 积跬步,聚小流------java信息生成图片

    需求: 是在做证书的时候碰到的这个问题. 当时需求是能够进行在线打印证书,第一次进行的操作是直接打印html,并且已经排好版(用jqprint插件)进行打印.在打印时碰到了兼容的问题,另外因为背景图片 ...