LG2024 [NOI2001]食物链
拆点法
用并查集维护每种动物的同类、天敌、食物群
#include<cstdio>
int fa[300005];
int n,k,ans;
inline int read()
{
int sum=0;
char ch=getchar();
while(ch>'9'||ch<'0') ch=getchar();
while(ch>='0'&&ch<='9') sum=sum*10+ch-48,ch=getchar();
return sum;
}//读入优化
int find(int x)
{
if(x!=fa[x]) fa[x]=find(fa[x]);
return fa[x];
}//查询
int unity(int x,int y)
{
int r1=find(fa[x]),r2=find(fa[y]);
fa[r1]=r2;
}//合并
int main()
{
int x,y,z;
n=read(),k=read();
for(int i=1;i<=3*n;++i) fa[i]=i; //对于每种生物:设 x 为本身,x+n 为猎物,x+2*n 为天敌
for(int i=1;i<=k;++i)
{
z=read(),x=read(),y=read();
if(x>n||y>n) {ans++; continue;} // 不属于该食物链显然为假
if(z==1)
{
if(find(x+n)==find(y)||find(x+2*n)==find(y)) {ans++; continue;}
//如果1是2的天敌或猎物,显然为谎言
unity(x,y); unity(x+n,y+n); unity(x+2*n,y+2*n);
//如果为真,那么1的同类和2的同类,1的猎物是2的猎物,1的天敌是2的天敌
}
else if(z==2)
{
if(x==y) {ans++; continue;} //其实是废话但是可以稍微省点时间
if(find(x)==find(y)||find(x+2*n)==find(y)) {ans++; continue;}
//如果1是2的同类或猎物,显然为谎言
unity(x,y+2*n); unity(x+n,y); unity(x+2*n,y+n);
//如果为真,那么1的同类是2的天敌,1的猎物是2的同类,1的天敌是2的猎物
}
}
printf("%d\n",ans);
return 0;
}
带权并查集法
- 如果X、Y是同类,可以用并查集并起来
- 但如果对于A、B、C三类分开保存,会存在一定问题
- 因为A、B、C之间存在着连续关系,比如A吃B、B吃C、C吃D,其实可以推导出A、D为同类
- 考虑将关系建成一张图,两个点之间路径的权值由关系决定。
- 如果u、v是同类,那么u->v路径权值为0
- 如果u吃v,那么u->v路径权值为1
- 如果v吃u,那么u->v路径权值为2
- 那么两个点之间的关系可以由两个点之间的路径得出(模3)。
- 但每次查询时找路径会有一个O(N)的复杂度
- 发现两个点之间的所有路径权值都是一样的,所以只需要保留一条
- 两个点之间的关系由这个权值来表示
- 知道了两个点分别与根的关系,就可以知道两个点之间的关系
- 带权并查集压缩路径的时候需要考虑当前点到新根的距离
- 复杂度O(K*alpha(N))
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<ctime>
#include<iostream>
#include<string>
#include<vector>
#include<list>
#include<deque>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<algorithm>
#include<complex>
#pragma GCC optimize ("O0")
using namespace std;
template<class T> inline T read(T&x){
T data=0;
int w=1;
char ch=getchar();
while(!isdigit(ch))
{
if(ch=='-')
w=-1;
ch=getchar();
}
while(isdigit(ch))
data=10*data+ch-'0',ch=getchar();
return x=data*w;
}
typedef long long ll;
const int INF=0x7fffffff;
const int MAXN=1e5+7;
int fa[MAXN],val[MAXN];
int find(int x)
{
if(fa[x]==x)
return x;
else
{
int fx=fa[x];
fa[x]=find(fa[x]);
val[x]=(val[x]+val[fx])%3;
return fa[x];
}
}
int main()
{
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
int n,k;
read(n);read(k);
for(int i=1;i<=n;++i)
fa[i]=i,val[i]=0;
int ans=0;
while(k--)
{
int opt,x,y;
read(opt);read(x);read(y);
if(x>n||y>n)
{
++ans;
continue;
}
if(opt==1)
{
int fx=find(x),fy=find(y);
if(fx==fy)
{
if((val[x]+3-val[y])%3!=0)
++ans;
}
else
{
fa[fx]=fy;
val[fx]=3-(val[x]+3-val[y])%3;
}
}
else if(opt==2)
{
if(x==y)
{
++ans;
continue;
}
int fx=find(x),fy=find(y);
if(fx==fy)
{
if((val[x]+3-val[y])%3!=1)
++ans;
}
else
{
fa[fx]=fy;
val[fx]=4-(val[x]+3-val[y])%3;
val[fx]%=3;
}
}
}
printf("%d\n",ans);
// fclose(stdin);
// fclose(stdout);
return 0;
}
LG2024 [NOI2001]食物链的更多相关文章
- NOI2001 食物链【扩展域并查集】*
NOI2001 食物链 动物王国中有三类动物 A,B,C,这三类动物的食物链构成了有趣的环形.A 吃 B,B吃 C,C 吃 A. 现有 N 个动物,以 1 - N 编号.每个动物都是 A,B,C 中的 ...
- 洛谷 P2024 [NOI2001]食物链 解题报告
P2024 [NOI2001]食物链 题目描述 动物王国中有三类动物 A,B,C,这三类动物的食物链构成了有趣的环形.A 吃 B,B 吃 C,C 吃 A. 现有 N 个动物,以 1 - N 编号.每个 ...
- 【题解】P2024 [NOI2001]食物链 - 数据结构 - 并查集
P2024 [NOI2001]食物链 声明:本博客所有题解都参照了网络资料或其他博客,仅为博主想加深理解而写,如有疑问欢迎与博主讨论✧。٩(ˊᗜˋ)و✧*。 题目描述 动物王国中有三类动物 \(A,B ...
- NOI2001 食物链
食物链 题目描述 动物王国中有三类动物 A,B,C,这三类动物的食物链构成了有趣的环形.A 吃 B,B 吃 C,C 吃 A. 现有 N 个动物,以 1 - N 编号.每个动物都是 A,B,C 中的一种 ...
- P2024 [NOI2001]食物链 并查集
题目描述 动物王国中有三类动物 A,B,C,这三类动物的食物链构成了有趣的环形.A 吃 B,B 吃 C,C 吃 A. 现有 N 个动物,以 1 - N 编号.每个动物都是 A,B,C 中的一种,但是我 ...
- 洛谷 P2024 [NOI2001]食物链 (并查集)
嗯... 题目链接:https://www.luogu.org/problemnew/show/P2024 这道题和团伙这道题的思想比较类似,都是一个数组分成几个集合,但这道题的思路更加混乱,建议没做 ...
- NOI2001食物链
描述 动物王国中有三类动物 A,B,C,这三类动物的食物链构成了有趣的环形.A吃B,B吃C,C吃A. 现有N个动物,以1-N编号.每个动物都是A,B,C中的一种,但是我们并不知道它到底是哪一种. 有人 ...
- [NOI2001] 食物链 (扩展域并查集)
题目描述 动物王国中有三类动物 A,B,C,这三类动物的食物链构成了有趣的环形.A 吃 B,B 吃 C,C 吃 A. 现有 N 个动物,以 1 - N 编号.每个动物都是 A,B,C 中的一种,但是我 ...
- 洛谷 P2024 [NOI2001]食物链
题意简述 有人用两种说法对这 N 个动物所构成的食物链关系进行描述: 1."1 X Y",表示 X 和 Y 是同类. 2."2 X Y",表示 X 吃 Y . ...
随机推荐
- sgu 126 Boxes
题意:较大的容量减较小的容量,较小的容量翻倍.问操作几回其中一个空. 开始用set判重,重复就不可行.不过状态最多有2e18种.不仅爆内存,还超时.然后找规律.发现只有比例为1:1,1:3,1:7,3 ...
- JavaScript的深拷贝和浅拷贝总结
深拷贝和浅拷贝 深拷贝:拷贝实例:浅拷贝:拷贝引用(原对象). 说深拷贝和浅拷贝之前,我先去了解了下高程书上的JavaScript的变量类型: 基本类型:undefined.null.Boolean. ...
- Tree CodeForces - 1111E (树,计数,换根)
大意: 给定树, 多组询问, 每个询问给出一个点集$S$, 给定$m, r$, 求根为$r$时, $S$的划分数, 满足 每个划分大小不超过$m$ 每个划分内不存在一个点是另一个点的祖先 设点$x$的 ...
- cf188C(最大子段和&&思维)
C. Functions again time limit per test 1 second memory limit per test 256 megabytes input standard i ...
- 基础最短路(模板 bellman_ford)
Description 在每年的校赛里,所有进入决赛的同学都会获得一件很漂亮的t-shirt.但是每当我们的工作人员把上百件的衣服从商店运回到赛场的时候,却是非常累的!所以现在他们想要寻找最短的从商店 ...
- MyBatis Generator自动创建代码
MyBatis Generator自动创建代码 1.首先在eclipse上安装mybatis插件 2.创建一个mavenWeb项目. 3.在resource中写入一个xml,一定要与我得同名 < ...
- BZOJ1299 [LLH邀请赛]巧克力棒
怎么又是博弈论...我去 Orz hzwer,这道题其实是可以转化成Nim游戏的! "第一步: 先从n根巧克力棒中取出m(m>0)根,使得这m根巧克力棒的xor和为0,同时使得剩下的n ...
- 微信小程序wx.chooseImage和wx.previewImage的综合使用(图片上传可以限制个数)
本例从微信小程序的组件扒下来的. WXML: <view class="weui-cell"> <view class="weui-cell__bd&q ...
- 基于GUI的简单聊天室02
服务器端 与上一篇相比,加进了线程内部类,解决多个客户端连接时,服务器无法全部响应的问题. 利用List集合来装载客户端的对象. 还需要注意全局变量的应用. /** * 相比01,加进了线程内部类,解 ...
- 【DevExpress v17.2新功能预告】改进DevExtreme编辑器
DevExpress即将发布v17.2版本,在DevExtreme v17.2中,DevExtreme编辑器进行了一些改进. 除了dxScheduler,dxDataGrid,dxTreeList和d ...