并查集

Codeforces1263D-Secret Passwords

不问归期 提交于 2019-12-06 16:44:02
题意 给n个字符串,两个字符串之间如果有相同的字符,那么两个就等价,等价关系可以传递,问最后有多少个等价类。 分析 考虑并查集或者dfs联通块,如果是并查集的话,对于当前字符串的某个字符,肯定要和这个字符在前面出现的某个字符串合并起来,所以维护每个字符的最后一次出现位置即可。 如果是dfs找联通块,建图就是把26个字符看成26个点,然后字符串分别连向这些字符,最后从字符节点dfs标记。 代码 dfs #include <bits/stdc++.h> using namespace std; const int N=2e6+50; int n; char s[55]; struct Edge{ int v,next; }e[N*2]; int cnt,head[N]; int ind[N]; void init(){ cnt=0; memset(head,-1,sizeof(head)); } void add(int u,int v){ e[cnt]=Edge{v,head[u]}; head[u]=cnt++; e[cnt]=Edge{u,head[v]}; head[v]=cnt++; } int v[30],vis[N]; void dfs(int u){ vis[u]=1; for(int i=head[u];i!=-1;i=e[i].next){ int v=e[i].v

HDU3047-Zjnu Stadium-带权并查集

别等时光非礼了梦想. 提交于 2019-12-06 15:25:47
In 12th Zhejiang College Students Games 2007, there was a new stadium built in Zhejiang Normal University. It was a modern stadium which could hold thousands of people. The audience Seats made a circle. The total number of columns were 300 numbered 1--300, counted clockwise, we assume the number of rows were infinite. These days, Busoniya want to hold a large-scale theatrical performance in this stadium. There will be N people go there numbered 1--N. Busoniya has Reserved several seats. To make it funny, he makes M requests for these seats: A B X, which means people numbered B must seat

并查集

柔情痞子 提交于 2019-12-06 12:16:58
排序问题 #include<iostream> #include<cstdio> #include<algorithm> int pre[10001]; using namespace std; struct node { int x,y,z,w; }q[10001]; int compare(node x,node y) { return x.z<y.z; } int find(int x) { int r=x; while(r!=pre[r]) r=pre[r]; return r;//可以不压缩 } int main() { int n; while(scanf("%d",&n)!=EOF&&n){ int f1,f2,sum=0; for(int i=1;i<=n;i++) { pre[i]=i; } for(int i=1;i<=(n-1)*n/2;i++) { scanf("%d %d %d %d",&q[i].x,&q[i].y,&q[i].z,&q[i].w); if(q[i].w==1) { f1=find(q[i].x); f2=find(q[i].y); if(f1!=f2) { pre[f2]=f1; } } } sort(q+1,q+(n-1)*n/2+1,compare);//这里出了问题 for(int i=1;i<=(n-1)*n/2;i++) {

CodeForces - 1253D(并查集)

微笑、不失礼 提交于 2019-12-06 06:56:11
题意 https://vjudge.net/problem/CodeForces-1253D 一个无向图,对于任意l,r,如果l到r有路径,那么l到m也有路径(l<m<r),问最少加多少条边,使得上述条件成立。 思路 先用并查集缩成若干个连通块,顺带把每个连通块的最大值求出来,然后我们从1到n开始遍历每个点,记录当前点所在连通块的最大值,然后如果i小于最大值而且和i-1不在一个连通块内,就合并这两个连通块。计算需要合并的次数即可。 代码 #include<bits/stdc++.h> using namespace std; #define inf 0x3f3f3f3f #define ll long long const int N=200005; const int mod=1e9+7; const double eps=1e-8; const double PI = acos(-1.0); #define lowbit(x) (x&(-x)) ll a[N],ans[N]; int main() { std::ios::sync_with_stdio(false); ll n,m; cin>>n>>m; for(int i=1;i<=n;i++) { cin>>a[i]; } sort(a+1,a+1+n); for(int i=1;i<=n;i++) { a[i]+=a[i

并查集

别说谁变了你拦得住时间么 提交于 2019-12-05 23:23:18
并查集 并查集一般两个函数,合并和查找(带路径压缩),合并是将父节点关联起来,查找是找父节点,然后层层减层路径压缩,即将它指向它父亲的父亲,因为首节点父亲的父亲也是它自己,所以不会越界。用pre记录他的父节点 下面是畅通工程题目: 畅通工程 *Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 84442 Accepted Submission(s): 44884 * Problem Description 某省调查城镇交通状况,得到现有城镇道路统计表,表中列出了每条道路直接连通的城镇。省政府“畅通工程”的目标是使全省任何两个城镇间都可以实现交通(但不一定有直接的道路相连,只要互相间接通过道路可达即可)。问最少还需要建设多少条道路? Input 测试输入包含若干测试用例。每个测试用例的第1行给出两个正整数,分别是城镇数目N ( < 1000 )和道路数目M;随后的M行对应M条道路,每行给出一对正整数,分别是该条道路直接连通的两个城镇的编号。为简单起见,城镇从1到N编号。 注意:两个城市之间可以有多条道路相通,也就是说 3 3 1 2 1 2 2 1 这种输入也是合法的 当N为0时,输入结束,该用例不被处理。 Output

第四周训练 | 并查集

随声附和 提交于 2019-12-05 18:12:04
A - How Many Tables #include<iostream> using namespace std; const int maxn = 1050; int set[maxn]; void init_set() { for(int i=0;i<=maxn;++i)set[i]=i; } int find_set(int x) { return x==set[x]?x:find_set(set[x]); } void union_set(int x,int y) { x=find_set(x); y=find_set(y); if(x!=y)set[x]=set[y]; } int main() { int t,n,m,x,y; cin>>t; while(t--) { cin>>n>>m; init_set(); for(int i=1;i<=m;++i) { cin>>x>>y; union_set(x,y); } int ans=0; for(int i=1;i<=n;++i) { if(set[i]==i)ans++; } cout<<ans<<endl; } return 0; } 优化版,降低了树高 #include<iostream> using namespace std; const int maxn = 1050; int set[maxn]

[bzoj 3732] Network (Kruskal重构树)

社会主义新天地 提交于 2019-12-05 14:58:55
https://blog.csdn.net/niiick/article/details/81952126 https://www.cnblogs.com/ZegWe/p/6243883.html Kruskal重构树—性质 1.是一个小/大根堆(由建树时边权的排序方式决定) 2.LCA(u,v)的权值是 原图 u到v路径上最大/小边权的最小/大值(由建树时边权的排序方式决定) Kruskal重构树—建树 模仿kruskal的过程 先将边权排序 (排序方式决定何种性质接下来说明) 依次遍历每条边 若改变连接的两个节点u和v 不在一个并查集内 就新建一个结点node 该点点权为这条边的边权 找到u,v所在并查集的根ui,vi u_i,v_iu i ​ ,v i ​ 连边(node,ui)(node,vi) (node,u_i)(node,v_i)(node,u i ​ )(node,v i ​ ) 并更新并查集fa[ui]=node,fa[vi]=node fa[u_i]=node,fa[v_i]=nodefa[u i ​ ]=node,fa[v i ​ ]=node 遍历完原图所有边后 我们建出来的必定是一棵树 也就是我们要的kruskal重构树 注意这棵树是以最后新建的结点为根的有根树 若原图不连通,即建出的是一个森林 那么就遍历每个节点,找到其并查集的根作为其所在树的根 1

图论500题

岁酱吖の 提交于 2019-12-05 12:08:38
【HDU】 1213 How Many Tables 基础并查集★ 1272 小希的迷宫 基础并查集★ 1325&&poj1308 Is It A Tree? 基础并查集★ 1856 More is better 基础并查集★ 1102 Constructing Roads 基础最小生成树★ 1232 畅通工程 基础并查集★ 1233 还是畅通工程 基础最小生成树★ 1863 畅通工程 基础最小生成树★ 1875 畅通工程再续 基础最小生成树★ 1879 继续畅通工程 基础最小生成树★ 3371 Connect the Cities 简单最小生成树★ 1301 Jungle Roads 基础最小生成树★ 1162 Eddy's picture 基础最小生成树★ 1198 Farm Irrigation 基础最小生成树★ 1598 find the most comfortable road 枚举+最小生成树★★ 1811 Rank of Tetris 并查集+拓扑排序★★ 3926 Hand in Hand 同构图★ 3938 Portal 离线+并查集★★ 2489 Minimal Ratio Tree dfs枚举组合情况+最小生成树★ 4081 Qin Shi Huang's National Road System 最小生成树+DFS★★??? 4126 Genghis

并查集超强解析

旧时模样 提交于 2019-12-05 06:40:33
前言 an是看了某大佬的文章忽然就懂了的。 一直很想写一个解析,可是苦于没时间。 现在终于出炉了。 正文 (有点幼稚勿喷,自编) 江湖上散落着各式各样的大侠。他们没有什么正当职业,整天背着剑在外面走来走去,碰到和自己不是一路人的,就免不了要打一架。但大侠们有一个优点就是讲义气,绝对不打自己的朋友。而且他们信奉“朋友的朋友就是我的朋友”,只要是能通过朋友关系串联起来的,不管拐了多少个弯,都认为是自己人。这样一来,江湖上就形成了一个一个的帮派,通过两两之间的朋友关系串联起来。而不在同一个帮派的人,无论如何都无法通过朋友关系连起来,于是就可以放心往死里打。 假设我们知道有pre[i]确定了i的上级(朋友),那么问题来了。 怎么确定两个人是同意帮派的人咧?只需要确定自己的队长是谁就好了,这时find函数就派上用场了: int find(int x) //查找根结点(队长) { while(x != pre[x]) //我的上级不是队长 x = pre[x]; return x;//返回队长 } 大诗仙李白听说这消息很是激动,拜师学剑,数载学成归来,约了武林高手花木LAN与荆轲二人商讨组建一个帮派,于是花木LAN和荆轲两人到处拉人。于是形成了“李白帮派”: 达摩本拜橘右京为师,组成帮派,可是达摩跟花木兰成为了好朋友。本来橘右京跟李白打得死去活来,风云搅动,这样一来,京京不得不停手:

P3402 【模板】可持久化并查集

六眼飞鱼酱① 提交于 2019-12-05 05:19:37
今天看到这道题,忽然不知道为何要线段树了\笑(出现了一些瞎搞的想法 然后就想到了操作树。。。 就是,我们可以离线,然后每个位置直接维护一个栈,记录历史信息。 然鹅我也不知道为什么常数很大 #include<bits/stdc++.h> #define R register int using namespace std; namespace Luitaryi { inline int g() { R x=0,f=1; register char s; while(!isdigit(s=getchar())) f=='-'?-1:f; do x=x*10+(s^48); while(isdigit(s=getchar())); return x*f; } const int N=200010; int n,m; bool ans[N]; struct node {bool op,f[2],flg[2]; int u,v,tu,tv;}mem[N<<1]; vector <int> fa[N],d[N]; vector <int> e[N]; inline int getf(int x) {return (fa[x][fa[x].size()-1]==x)?x:getf(fa[x][fa[x].size()-1]);} inline void operation(int x) { if