[kuangbin带你飞]专题五 并查集 题解+总结
kuangbin带你飞:点击进入新世界
总结:
本人算是初学者中的初学者,欢迎交流~
并查集的接触过的不多,大概只有普通并查集,带权并查集,种族并查集,传说中的可持续化并查集只是听说过还没有接触,不过种族并查集可以用带权并查集来做,带权的话又常常跟dp联系在一起,普通并查集可以作为其他算法的一项工具。
kuangbin的题型:
A.普通并查集 参考1.2.3.6.9
B.带权并查集 参考4.5.7.8
C.并查集+DP
kuangbin之外:
[并查集模板]:待更
文章目录
- 总结:
- 1.Wireless Network
- 2.The Suspects
- 3.How Many Tables
- 4.How Many Answers Are Wrong
- 5.食物链
- 6.Supermarket
- 7.Parity game
- 8.A Bug's Life
- 9.Is It A Tree?
1.Wireless Network
原题链接:传送门
思路:
- 两点之间的距离预处理map[i][j]表示是否能够通信。
- 指令是o , 要先维护后才能通信。
- 维护一个点之后判断有没有可以其他可以进行通信的点,如果有就加入该点的集合。
代码如下:
#include<iostream>
#include<cstdio>
#define ll long long
#define R register int
#define inf 0x3f3f3f3f
using namespace std;
const int manx=1e3+5;
int a[manx],x[manx],y[manx],vis[manx];
bool map[manx][manx];
int n,d,u,v,l,r;
int find(int f)
{if(a[f]==f) return f;return a[f]=find(a[f]);
}
int main()
{cin>>n>>d;for(int i=1;i<=n;i++){scanf("%d%d",&x[i],&y[i]);a[i]=i;}for(int i=1;i<=n;i++)for(int j=i+1;j<=n;j++)if((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j])<=d*d)map[i][j]=map[j][i]=true;char c;while(cin>>c){if(c=='O'){scanf("%d",&l);vis[l]=1;for(int r=1;r<=n;r++){if(r!=l&&map[l][r]&&vis[r]){u=find(l),v=find(r);if(u==v) continue;a[u]=v;}}}else if(c=='S'){scanf("%d%d",&l,&r);l=find(l),r=find(r);if(l==r) printf("SUCCESS\n");else printf("FAIL\n");}}return 0;
}
2.The Suspects
原题链接:传送门
思路:
- 模板题,一步一步加入集合,最后判断有多少人跟0在同一个集合就行了。
代码如下:
#include<iostream>
#include<cstdio>
#define ll long long
#define R register int
#define inf 0x3f3f3f3f
using namespace std;
const int manx=3e4+5;
int a[manx];
int find(int x)
{if(a[x]==x) return x;return a[x]=find(a[x]);
}
int main()
{int n,m,u,v;while(cin>>n>>m){if(n==0&&m==0) break;for(int i=0;i<n;i++) a[i]=i;while(m--){int q;cin>>q>>u;for(int i=1;i<q;i++){cin>>v;a[find(u)]=find(v);u=v;}}int ans=0;for(int i=0;i<n;i++)if(find(a[i])==find(0))ans++;cout<<ans<<endl;}return 0;
}
3.How Many Tables
原题链接:传送门
思路:
- 求集合的个数,在连接的时候进行判断即可。
代码如下:
#include<iostream>
#include<cstdio>
using namespace std;
const int manx=1e3+5;
int a[manx];
int n,m;
int find(int x)
{if(a[x]==x) return x;else return a[x]=find(a[x]);
}
void show()
{for(int i=1;i<=n;i++)a[i]=i;
}
int main()
{int t;cin>>t;while(t--){scanf("%d %d",&n,&m);int ans=0;show();for(int i=1;i<=m;i++){int u,v;scanf("%d %d",&u,&v);u=find(u),v=find(v);if(u!=v) ans++;a[u]=v;}printf("%d\n",n-ans);}return 0;
}
4.How Many Answers Are Wrong
原题链接:传送门
思路:
- 给一些区间以及其区间和,判断假话语句数量。
- 带权并查集的模板题,根据输入连点,如果已经连好线,判断权值是否相等。
- 关于带权并查集可参考文章开头的模板,欢迎交流。
代码如下:
#include<iostream>
#include<cstdio>
#define ll long long
#define R register int
#define inf 0x3f3f3f3f
using namespace std;
const int manx=3e5+5;
int a[manx],d[manx];
int find(int x)
{if(a[x]==x) return x;int fa=find(a[x]);d[x]=d[x]+d[a[x]];return a[x]=fa;
}
int main()
{int n,m;while(scanf("%d%d",&n,&m)!=EOF){int ans=0;for(int i=0;i<=n;i++) a[i]=i,d[i]=0;for(int i=1;i<=m;i++){int u,v,w;scanf("%d%d%d",&u,&v,&w);u--;int x=find(u),y=find(v);if(x==y&&d[v]-d[u]!=w) ans++;else {if(x<y) a[y]=x,d[y]=d[u]+w-d[v];else a[x]=y,d[x]=d[v]-w-d[u];}}cout<<ans<<endl;}return 0;
}
5.食物链
原题链接:传送门
思路:
- 同上题,带权并查集入门题目,也可以说是种族并查集,那么只要对权值进行取模即可。
- 注意更新权值的时候需要+3再取模,防止出现负数。
代码如下:
#include<iostream>
#include<cstdio>
#define ll long long
#define R register int
#define inf 0x3f3f3f3f
using namespace std;
const int manx=3e5+5;
int a[manx],d[manx];
int find(int x)
{if(a[x]==x) return x;int fa=find(a[x]);d[x]=(d[x]+d[a[x]])%3;return a[x]=fa;
}
int main()
{int n,m,ans=0;scanf("%d%d",&n,&m);for(int i=0;i<=n;i++) a[i]=i,d[i]=0;for(int i=1;i<=m;i++){int u,v,w;scanf("%d%d%d",&w,&u,&v);w--;if(u>n||v>n||(w==2&&u==v)) ans++;else {int x=find(u),y=find(v);if(x==y&&(d[v]-d[u]+3)%3!=w) ans++;else {a[y]=x;d[y]=(d[u]+w-d[v]+3)%3;}}}cout<<ans<<endl;return 0;
}
6.Supermarket
原题链接:传送门
思路:
- 这道题本来是用贪心来做的,这里参考kuangbin大佬的做法,将并查集作为一个工具,记录每个商品至多能在什么时候卖出。
代码如下:
#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<algorithm>
using namespace std;
const int manx=1e4+5;
int a[manx];
struct node{int w,id;
}d[manx];
bool cmp(node a,node b){return a.w>b.w;
}
int find(int x)
{if(a[x]==-1) return x;else return a[x]=find(a[x]);
}
int main()
{int n;while(cin>>n){for(int i=1;i<=n;i++) cin>>d[i].w>>d[i].id;memset(a,-1,sizeof(a));sort(d+1,d+1+n,cmp);int ans=0;for(int i=1;i<=n;i++){int p= find(d[i].id);if(p>0){ans+=d[i].w;a[p]=p-1;}}cout<<ans<<endl;}return 0;
}
7.Parity game
原题链接:传送门
思路:
- 跟上面那道区间和相关的带权并查集差不多,不过这里只有奇偶两种情况,那么就是对2取模,即只有01两种情况,因此可以直接异或。
- 主要问题还是多了离散化,数据过大无法创建那么大的节点数组,因此可以把数据映射到一个新的数组里面。
代码如下:
#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<algorithm>
using namespace std;
const int manx=1e4+5;
struct node{int l,r;char s[10];
}q[manx];
int a[manx],d[manx],f[manx];
int find(int x)
{if(a[x]==x)return x;else{int root=find(a[x]);d[x]^=d[a[x]];return a[x]=root;}
}
int main(){int n,m,k=0;scanf("%d%d",&n,&m);for(int i=1;i<=m;i++){scanf("%d%d%s",&q[i].l,&q[i].r,&q[i].s);q[i].l--;f[++k]=q[i].l,f[++k]=q[i].r;}sort(f+1,f+1+k);k=unique(f+1,f+1+k)-f-1;for(int i=1;i<=k;i++) a[i]=i,d[i]=0;int i;for(i=1;i<=m;i++){int l=lower_bound(f+1,f+1+k,q[i].l)-f;int r=lower_bound(f+1,f+1+k,q[i].r)-f;int u=find(l),v=find(r);int w=0;if(q[i].s[0]=='o') w=1;if(u==v&&d[l]^w!=d[r]) break;else if(u<v) a[u]=v,d[u]=d[l]^d[r]^w;else if(u>v) a[v]=u,d[v]=d[l]^d[r]^w;}cout<<i-1<<endl;return 0;
}
8.A Bug’s Life
原题链接:传送门
思路:
- 跟上道题一样,只有两种情况,一种同性恋,一种异性恋,所以可以用xor来维护权值数组。
代码如下:
#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
using namespace std;
const int manx=2e4+5;
int a[manx],d[manx];
int find(int x)
{if(a[x]==x) return x;else {int fa=find(a[x]);d[x]^=d[a[x]];return a[x]=fa;}
}
int main()
{int t,T=1;scanf("%d",&t);while(t--){int n,m,flag=0;scanf("%d%d",&n,&m);for(int i=0;i<=n;i++) a[i]=i,d[i]=0;for(int i=1;i<=m;i++){int u,v;scanf("%d%d",&u,&v);if(flag) continue;int fu=find(u),fv=find(v);if(fu==fv){if(d[u]==d[v])flag=1;}else a[fv]=fu,d[fv]=d[u]^d[v]^1;}cout<<"Scenario #"<<T++<<":"<<endl;if(flag) puts("Suspicious bugs found!");else puts("No suspicious bugs found!");cout<<endl;}return 0;
}
9.Is It A Tree?
原题链接:传送门
思路:
- 连通无环,即点数比边数大一。
代码如下:
#include<iostream>
#include<set>
#include<cstring>
#include<cstdio>
using namespace std;
int main()
{int n,m;while(cin>>n>>m){if(n==-1&&m==-1) break;if(!n&&!m){puts("Yes");continue;}set<int>q;q.insert(n),q.insert(m);int ans=1;while(cin>>n>>m){if(!n&&!m) break;ans++;q.insert(n),q.insert(m);}if(ans==q.size()-1) puts("Yes");else puts("No");}return 0;
}
[kuangbin带你飞]专题五 并查集 题解+总结相关推荐
- hdu 1213 How Many Tables ([kuangbin带你飞]专题五 并查集)
点击打开链接 C - How Many Tables Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & ...
- [kuangbin带你飞]专题五 并查集 A - Wireless Network
A - Wireless Network 题目链接:https://vjudge.net/contest/66964#problem/A 题目: An earthquake takes place i ...
- [kuangbin带你飞]专题五 并查集 E - 食物链 (带权并查集)
E - 食物链 题目链接:https://vjudge.net/contest/66964#problem/E 动物王国中有三类动物A,B,C,这三类动物的食物链构成了有趣的环形.A吃B, B吃C,C ...
- [kuangbin带你飞]专题十二 基础DP1 题解+总结
kuangbin带你飞:点击进入新世界 总结: 简单dp,最近在做,持续更新. 文章目录 总结: 1.Max Sum Plus Plus 2.Ignatius and the Princess IV ...
- [kuangbin带你飞]专题五查并集
写了几个查并集得题,成功把自己写晕了 之后写下面得题(写不下去了) **poj-2912 poj 文章目录 1.POJ - 1611(模板题) 2.HDU - 1213(模板题) 3.poj2236( ...
- kuangbin带你飞专题合集
题目列表 [kuangbin带你飞]专题一 简单搜索 [kuangbin带你飞]专题二 搜索进阶 [kuangbin带你飞]专题三 Dancing Links [kuangbin带你飞]专题四 最短路 ...
- kuangbin带你飞 专题1-23 题单
kuangbin大神,对于打过ACM比赛的ACMer,无人不知无人不晓. 在此,附上vjudge平台上一位大神整理的[kuangbin带你飞]专题目录链接. [kuangbin带你飞专题目录1-23] ...
- “kuangbin带你飞”专题计划——专题十四:数论基础
写在前面 1.目前还没啥写的.开始时间:2021-05-13(其实博客上看得到该博客创建时间的) 2.上一个专题刷的是网络流(博客总结),属于第一次接触.本来想的是一周特别高效,然后一周略划水,结果是 ...
- (2021-07-14~)“kuangbin带你飞”专题计划——专题十三:基础计算几何
目录 前言 参考博客 自己总结的东西: 难度判断? 题目 1.[TOYS POJ - 2318 ](解决) 2.[Toy Storage POJ - 2398 ](解决) 3.[Segments PO ...
最新文章
- iOS App 崩溃报告符号化
- HDU1074 Doing Homework
- JDBC常见面试题集锦(一)
- 【Linux】一步一步学Linux——tar命令(62)
- MySQL --- 计算指定日期为当月的第几周
- 荣耀鸿蒙系统开机动画,荣耀赵明:鸿蒙系统首发设备欲屏蔽开机广告
- netty接收大文件的方法
- azul java_Java版本更新重大提醒 - Azul
- ViBe(Visual Background extractor)背景建模或前景检测
- 2017.10.1 互不侵犯king 思考记录
- reids高可用(灾难备份-持久化)
- Http Core学习(Http Components 翻译和学习)
- 10个最常见的 HTML5 面试题及答案
- CoreOS发起的友好兼容Kubernetes的存储系统:Torus
- python并行编程 - 介绍篇
- 论文阅读《“The Boating Store Had Its Best Sail Ever”: Pronunciation-attentive ....》
- 被老婆赶出家门,男子嚎啕大哭:击垮一个成年人,一次失业就够了
- 开正式发票到底谁交税
- MySQL(一): 初涉MySQL
- linux下实现root用户和其他用户之间转换