283 条题解
-
22
Rssqzqyp LV 7 @ 8 年前
首先这是一道显然的并查集模版题。
如果不知道并查集是什么,可以理解为一个个集合,不断合并集合。
看到题解里有用启发式合并的,不过此题显然没什么必要。求赞<
求顶<
谢谢< -
37 年前@
并查集模板题(○’ω’○)(带路径压缩)
-
11 年前@
-
13 年前@
-
16 年前@
路压+按秩
-
16 年前@
模板题
#include<iostream>
using namespace std;
const int maxn = 1000000;
int n,m,p,f[maxn];
int init(){
for (int i = 1;i<=n;i++)
f[i] = i;
return 0;
}
int ffind(int v){
if (f[v]==v)
return v;
else
{
f[v] = ffind(f[v]);
return f[v];
}
}
void hm(int u,int v){
int t1,t2;
t1 = ffind(u);
t2 = ffind(v);
if (t1!=t2)
{
f[t2] = t1;
}
return;
}
int judge(int u,int v){
int t1,t2;
t1 = ffind(u);
t2 = ffind(v);
if (t1!=t2)
{
return 0;
}
return 1;
}
int main()
{
// freopen("testi.txt","r",stdin);
cin >> n >> m >> p;
init();for (int i = 1; i<=m; i++){
int x,y;
cin >> x >> y;
hm(x,y);
}for (int i = 1;i<=p;i++){
int x,y;cin >> x >> y;
if (judge(x,y))
cout << "Yes" << endl;
else
cout << "No" << endl;}
return 0;
} -
17 年前@
-
17 年前@
简单的一个并查集,不断合并并查集即可
-
18 年前@
-
18 年前@
简单的并查集(路径压缩 + 按秩合并)。
注:数组起名不能叫 rank。 -
05 年前@
-
07 年前@
*****简单的并查集*****
-
07 年前@
-
08 年前@
#include<iostream>
#include<cstdio>
using namespace std;int pre[5010];
int find(int x)
{
int r=x;
while(pre[r]!=r)
r=pre[r];int i=x,j;
while(pre[i]!=i)
{
j=pre[i];
pre[i]=r;
i=j;
}return r;
}void mix(int a,int b)
{
int fa=find(a),fb=find(b);
if(fa!=fb)
{
pre[fa]=fb;
}
}int main()
{
int n,m,p;
scanf("%d %d %d",&n,&m,&p);for(int i=1;i<=n;i++)
{
pre[i]=i;
}for(int i=0;i<m;i++)
{
int a,b;
scanf("%d %d",&a,&b);mix(a,b);
}for(int i=0;i<p;i++)
{
int a,b;
scanf("%d %d",&a,&b);if(find(a)==find(b))
{
printf("Yes\n");
}else
printf("No\n");
}return 0;
} -
08 年前@
简单的并查集
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int f[10001];
int N, M, P;int find(int x) {
return f[x]==x ? x : find(f[x]);
}void hb(int r1, int r2) { f[r2] = r1; }
void init() {
scanf("%d%d%d", &N, &M, &P);
for(int i=1; i<=N; i++) f[i] = i;
for(int i=1; i<=M; i++) {
int x, y;
scanf("%d%d", &x, &y);
int r1 = find(x);
int r2 = find(y);
if(r1 != r2) hb(r1, r2);
}
for(int i=1; i<=P; i++) {
int x, y;
scanf("%d%d", &x, &y);
if(find(x) != find(y)) printf("No\n");
else printf("Yes\n");
}
}int main() {
init();
return 0;
} -
08 年前@
#主要用数组表示标示符
type int=longint;
var
fam : array[1..10000] of int;
n,m,p,i,a,b : int;
function fa(c :int):int;
begin
if fam[c]=c then exit(c);
fam[c]:=fa(fam[c]);
exit(fam[c]);
end;
procedure isfam(x,y :int);
begin
fam[fa(x)]:=fa(y);
end;begin
readln(n,m,p);
for i := 1 to n do fam[i] :=i;
for i := 1 to m do
begin
readln(a,b);
isfam(a,b);
end;
for i := 1 to p do
begin
readln(a,b);
if fa(a)=fa(b) then writeln('Yes')
else writeln('No');
end;end.
-
08 年前@
解的第20个题,纪念一下,这棵裸的并查集
```c++#include <iostream>
#include <fstream>#include <vector>
#include <algorithm>
#include <cstring>using namespace std;
const int MAX_N = 5000 + 50;
int par[MAX_N]; // 父亲
int ranki[MAX_N]; // 树的高度// 初始化n个元素
void init(int n)
{
for (int i = 0; i < n; i++)
{
par[i] = i;
ranki[i] = 0;
}
}// 查询树的根
int find(int x)
{
if (par[x] == x)
return x;
else
return par[x] = find(par[x]);
}// 合并x和y所属的集合
void unite(int x, int y)
{
x = find(x);
y = find(y);
if (x == y) return;if (ranki[x] < ranki[y]) {
par[x] = y;
}
else {
par[y] = x;
if (ranki[x] == ranki[y])
ranki[x]++;
}
}// 判断x和y是否属于同一个集合
bool same(int x, int y)
{
return find(x) == find(y);
}int main()
{
#ifdef LOCAL
freopen("input.txt", "r", stdin);
//freopen("output.txt", "w", stdout);
#endifint n, m, p; cin >> n >> m >> p;
init(n);int a, b;
for (int i = 0; i < m; ++i) {
cin >> a >> b;
unite(a, b);
}
for (int i = 0; i < p; ++i) {
cin >> a >> b;
cout << (same(a, b) ? "Yes" : "No") << endl;
}return 0;
} -
08 年前@
pascal 和 C++并查集
###pascal code
program ex;
var fa:array[1..5000] of longint;
i,j,n,m,p,k1,k2:longint;
ans:string;
function father(x:longint):longint;
begin
if fa[x]=x then exit(x);
fa[x]:=father(fa[x]); exit(fa[x]);
end;procedure add(a,b:longint);
var f1,f2:longint;
begin
f1:=father(a); f2:=father(b); fa[f2]:=f1;
end;function search(a1,a2:longint):string;
begin
if father(a1)=father(a2) then
exit('Yes')
else
exit('No');
end;begin //main
read(n,m,p);
for i:=1 to n do fa[i]:=i;for i:=1 to m do begin
read(k1,k2); add(k1,k2);
end;for i:=1 to p do begin
read(k1,k2); ans:=search(k1,k2); writeln(ans);
end;end.
C++ code
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <algorithm>
#include <iostream>
#include <ctype.h>
#include <set>
#define maxn 1000000
using namespace std;int fa[5100],i,m,p,n,a,b;
int getfather(int x){
if(fa[x]==x){return x;}
fa[x]=getfather(fa[x]);
return fa[x];
}void add(int x,int y){
x=getfather(x); y=getfather(y); fa[y]=x;
}int main(){
scanf("%d%d%d",&n,&m,&p);
for(i=1;i<=n;i++){fa[i]=i;}
for(i=1;i<=m;i++){
scanf("%d%d",&a,&b); add(a,b);
}
for(i=1;i<=p;i++){
scanf("%d%d",&a,&b);
if(getfather(a)==getfather(b)){printf("Yes\n");}
else{printf("No\n");}
}return 0;
} -
08 年前@
并查集水题
#include <cstdio>const int size = 6005;
int n,m,p,f[size];int getfather(int x){
if(f[x] == x) return f[x];
else return f[x] = getfather(f[x]);
}void Union(int x, int y){
int fx = getfather(x);
int fy = getfather(y);if( fx != fy ) f[fy] = fx;
}int main(int argc, char const *argv[]){
scanf("%d %d %d",&n,&m,&p);
for(int i = 1; i <= n; i++) f[i] = i;for(int i = 1; i <= m; i++){
int x,y;
scanf("%d %d",&x,&y);
Union(x, y);
}for(int i = 1; i <= p; i++){
int x,y;
scanf("%d %d",&x,&y);
if( getfather(x) != getfather(y) ) printf("No\n");
else printf("Yes\n");
}return 0;
} -
08 年前@
正宗大水题 并查集经典模板
```#include<algorithm>
#include<cstring>
#include<cstdio>
using namespace std;int i,j,k,n,m,q,x,y;
int a[100001];inline int findroot(int t){
int path[10001],k=0,fr,root=t;
while (a[root]!=root){
path[++k]=root;
root=a[root];
}
fr=root;
for (int i=1;i<=k;i++) a[path[i]]=root;
return fr;
}int main(){
scanf("%d%d%d",&n,&m,&q);
for (i=1;i<=n;i++) a[i]=i;
for (i=1;i<=m;i++){
scanf("%d%d",&x,&y);
int r1=findroot(x);
int r2=findroot(y);
if (r1!=r2) a[r2]=r1;
}
for (i=1;i<=q;i++){
scanf("%d%d",&x,&y);
if (findroot(x)==findroot(y)) printf("Yes\n");
else printf("No\n");
}
}```