并查集

A - Wireless Network

题意:
所有电脑遭到攻击,需逐个修复,每次修复一台电脑,每台电脑的坐标为(xi,yi),当两台电脑A,B都修复好且它们之间的距离小于等于d,A,B联通,或者存在一台电脑 C, A,B,C都修复好且A,C之间的距离小于等于d,B,C距离小于等于d,那么A,B联通。操作符“O”代表修复电脑,操作符“S”代表查询。

题解:
suc数组记录修理好的电脑的序号,如果两台电脑联通,那么使用并查集记录,将这两台电脑合并到一起表示联通,查询时只需判断是否为相同父亲节点即可。

AC_Code:

//
//Write by Yuan Xilan on 2019...
//
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<string>
#include<iostream>
#include<sstream>
#include<set>
#include<map>
#include<queue>
#include<bitset>
#include<vector>
#include<limits.h>
#include<assert.h>
#define SZ(X) ((int)(X).size())
#define ALL(X) (X).begin(), (X).end()
#define REP(I, N) for (int I = 0; I < (N); ++I)
#define REPP(I, A, B) for (int I = (A); I < (B); ++I)
#define FOR(I, A, B) for (int I = (A); I <= (B); ++I)
#define FORS(I, S) for (int I = 0; S[I]; ++I)
#define RS(X) scanf("%s", (X))
#define SORT_UNIQUE(c) (sort(c.begin(),c.end()), c.resize(distance(c.begin(),unique(c.begin(),c.end()))))
#define GET_POS(c,x) (lower_bound(c.begin(),c.end(),x)-c.begin())
#define CASET int ___T; scanf("%d", &___T); for(int cs=1;cs<=___T;cs++)
#define MP make_pair
#define PB push_back
#define MS0(X) memset((X), 0, sizeof((X)))
#define MS1(X) memset((X), -1, sizeof((X)))
#define LEN(X) strlen(X)
#define F first
#define S second
using namespace std;
typedef long long ll,LL;
typedef unsigned long long ull;
typedef long double ld;
typedef pair<int,int> PII;
typedef vector<int> VI;
typedef vector<LL> VL;
typedef vector<PII> VPII;
typedef pair<LL,LL> PLL;
typedef vector<PLL> VPLL;
void R() {}
#ifdef HOME
 #define DEBUG(...) {printf("# ");printf(__VA_ARGS__);puts("");}
#else
 #define DEBUG(...)
#endif
const int maxn = 1009;
int father[maxn];
int suc[maxn];//修理好的电脑
double x[maxn], y[maxn];
int n,d;

double __distance(int a, int b){
	return sqrt((y[b] - y[a]) * (y[b] - y[a]) + (x[b] - x[a]) * (x[b] - x[a]));
}

void init(){
	for(int i=1; i<=1008; ++i){
		father[i] = i;
	}
}

int get_father(int a){
	if(father[a] == a){
		return a;
	}
	return father[a] = get_father(father[a]);
}

void merge(int a, int b){
	a = get_father(a);
	b = get_father(b);
	if(a != b){
		father[a] = b;
	}
}


int main(){
	while(cin >> n >> d){
		int cnt = 0;
		init();
		double tx,ty;
		for(int i=1; i<=n; ++i){
			cin >> tx >> ty;
			x[i] = tx;
			y[i] = ty;
		}
		char ch;
		while(cin >> ch){
			switch(ch){
				case 'O':
					int k;
					cin >> k;
					for(int i=0; i<cnt; ++i){
						if(__distance(k, suc[i]) <= d){
							merge(k,suc[i]);
						}
					}
					suc[cnt++] = k;
					break;
				case 'S':
					int a,b;
					cin >> a >> b;
					if(get_father(a) == get_father(b)) puts("SUCCESS");
					else puts("FAIL");
			}
		}
	}
}

B - The Suspects

题意:小明感染上病毒,只要是同个小组的就有可能感染病毒,有m个小组,问最多可能感染数目。

题解:
并查集模版。

//
//Write by Yuan Xilan on 2019...
//
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<string>
#include<iostream>
#include<sstream>
#include<set>
#include<map>
#include<queue>
#include<bitset>
#include<vector>
#include<limits.h>
#include<assert.h>
#define SZ(X) ((int)(X).size())
#define ALL(X) (X).begin(), (X).end()
#define REP(I, N) for (int I = 0; I < (N); ++I)
#define REPP(I, A, B) for (int I = (A); I < (B); ++I)
#define FOR(I, A, B) for (int I = (A); I <= (B); ++I)
#define FORS(I, S) for (int I = 0; S[I]; ++I)
#define RS(X) scanf("%s", (X))
#define SORT_UNIQUE(c) (sort(c.begin(),c.end()), c.resize(distance(c.begin(),unique(c.begin(),c.end()))))
#define GET_POS(c,x) (lower_bound(c.begin(),c.end(),x)-c.begin())
#define CASET int ___T; scanf("%d", &___T); for(int cs=1;cs<=___T;cs++)
#define MP make_pair
#define PB push_back
#define MS0(X) memset((X), 0, sizeof((X)))
#define MS1(X) memset((X), -1, sizeof((X)))
#define LEN(X) strlen(X)
#define F first
#define S second
using namespace std;
typedef long long ll,LL;
typedef unsigned long long ull;
typedef long double ld;
typedef pair<int,int> PII;
typedef vector<int> VI;
typedef vector<LL> VL;
typedef vector<PII> VPII;
typedef pair<LL,LL> PLL;
typedef vector<PLL> VPLL;
void R() {}
#ifdef HOME
 #define DEBUG(...) {printf("# ");printf(__VA_ARGS__);puts("");}
#else
 #define DEBUG(...)
#endif
const int maxn = 34567;
int father[maxn];
int src[maxn];
int n,m;

void init(){
	for(int i=0; i<=34555; ++i){
		father[i] = i;
	}
}

int get_father(int x){
	if(father[x] == x) return x;
	return father[x] = get_father(father[x]);
}

void merge(int x, int y){
	x = get_father(x);
	y = get_father(y);
	if(x != y){
		father[x] = y;
	}
}

int main(){
	while(cin >> n >> m){
		if(n == 0 && m == 0) break;
		init();
		while(m--){
			int k,h,j;
			cin >> k;
			cin >> h;
			for(int i=2; i<=k; ++i){
				cin >> j;
				merge(h,j);
			}
		}
		int sum = 1;
		for(int i=1; i<=n; ++i){
			if(get_father(i) == get_father(0)) sum += 1;
		}
		cout << sum << endl;
	}
}

C - How Many Tables

题意:
n个人,有m组关系,互相认识的可以坐在一起吃饭,问最少的桌子数。

题解:
并查集裸体。

//
//Write by Yuan Xilan on 2019...
//
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<string>
#include<iostream>
#include<sstream>
#include<set>
#include<map>
#include<queue>
#include<bitset>
#include<vector>
#include<limits.h>
#include<assert.h>
#define SZ(X) ((int)(X).size())
#define ALL(X) (X).begin(), (X).end()
#define REP(I, N) for (int I = 0; I < (N); ++I)
#define REPP(I, A, B) for (int I = (A); I < (B); ++I)
#define FOR(I, A, B) for (int I = (A); I <= (B); ++I)
#define FORS(I, S) for (int I = 0; S[I]; ++I)
#define RS(X) scanf("%s", (X))
#define SORT_UNIQUE(c) (sort(c.begin(),c.end()), c.resize(distance(c.begin(),unique(c.begin(),c.end()))))
#define GET_POS(c,x) (lower_bound(c.begin(),c.end(),x)-c.begin())
#define CASET int ___T; scanf("%d", &___T); for(int cs=1;cs<=___T;cs++)
#define MP make_pair
#define PB push_back
#define MS0(X) memset((X), 0, sizeof((X)))
#define MS1(X) memset((X), -1, sizeof((X)))
#define LEN(X) strlen(X)
#define F first
#define S second
using namespace std;
typedef long long ll,LL;
typedef unsigned long long ull;
typedef long double ld;
typedef pair<int,int> PII;
typedef vector<int> VI;
typedef vector<LL> VL;
typedef vector<PII> VPII;
typedef pair<LL,LL> PLL;
typedef vector<PLL> VPLL;
void R() {}
#ifdef HOME
 #define DEBUG(...) {printf("# ");printf(__VA_ARGS__);puts("");}
#else
 #define DEBUG(...)
#endif
const int maxn = 34567;
int father[maxn];
int src[maxn];
int n,m,t;

void init(){
	for(int i=0; i<=34555; ++i){
		father[i] = i;
	}
}

int get_father(int x){
	if(father[x] == x) return x;
	return father[x] = get_father(father[x]);
}

void merge(int x, int y){
	x = get_father(x);
	y = get_father(y);
	if(x != y){
		father[x] = y;
	}
}

int main(){
	while(cin >> t){
		while(t--){
			init();
			cin >> n >> m;
			while(m--){
				int a,b;
				cin >> a >> b;
				merge(a,b);
			}
			set<int>j;
			for(int i=1; i<=n; ++i){
				j.insert(get_father(i));
			}
			cout << j.size() << endl;
		}
	}
}

L - 小希的迷宫

题意:
判断一个迷宫是不是满足从任意一个点到另一个点有且仅有一条简单路径。

题解:
并查集在合并边的时候如果有两个点的爸爸一样,那么不符合题意,又因为任意两点,所以图必须联通。

PS:此题坑点,2 3 3 2 0 0
AC_Code:

//
//Write by Yuan Xilan on 2019...
//
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<string>
#include<iostream>
#include<sstream>
#include<set>
#include<map>
#include<queue>
#include<bitset>
#include<vector>
#include<limits.h>
#include<assert.h>
#define SZ(X) ((int)(X).size())
#define ALL(X) (X).begin(), (X).end()
#define REP(I, N) for (int I = 0; I < (N); ++I)
#define REPP(I, A, B) for (int I = (A); I < (B); ++I)
#define FOR(I, A, B) for (int I = (A); I <= (B); ++I)
#define FORS(I, S) for (int I = 0; S[I]; ++I)
#define RS(X) scanf("%s", (X))
#define SORT_UNIQUE(c) (sort(c.begin(),c.end()), c.resize(distance(c.begin(),unique(c.begin(),c.end()))))
#define GET_POS(c,x) (lower_bound(c.begin(),c.end(),x)-c.begin())
#define CASET int ___T; scanf("%d", &___T); for(int cs=1;cs<=___T;cs++)
#define MP make_pair
#define PB push_back
#define MS0(X) memset((X), 0, sizeof((X)))
#define MS1(X) memset((X), -1, sizeof((X)))
#define LEN(X) strlen(X)
#define F first
#define S second
using namespace std;
typedef long long ll,LL;
typedef unsigned long long ull;
typedef long double ld;
typedef pair<int,int> PII;
typedef vector<int> VI;
typedef vector<LL> VL;
typedef vector<PII> VPII;
typedef pair<LL,LL> PLL;
typedef vector<PLL> VPLL;
void R() {}
#ifdef HOME
 #define DEBUG(...) {printf("# ");printf(__VA_ARGS__);puts("");}
#else
 #define DEBUG(...)
#endif
const int maxn = 134567;
int father[maxn];
int src[maxn];
int n,m,t;
bool flag = true;

void init(){
	for(int i=1; i<=134555; ++i){
		father[i] = i;
	}
}

int get_father(int x){
	if(father[x] == x) return x;
	return father[x] = get_father(father[x]);
}

void merge(int x, int y){
	x = get_father(x);
	y = get_father(y);
	if(x != y){
		father[x] = y;
	}
	else flag = false;
}

int main(){
	while(cin >> n >> m){
		if(n == 0 && m == 0){
			puts("Yes");
			continue;
		}
		vector<int>s1;
		set<int>s2;
		flag = true;
		init();
		if(n == -1 && m == -1) break;
		merge(n, m);
		s1.push_back(n);
		s1.push_back(m);
		while(1){
			cin >> n >> m;
			if(n == 0 && m == 0) break;
			s1.push_back(n);
			s1.push_back(m);
			merge(n, m);
		}
		for(int i=0; i<s1.size(); ++i){
			s2.insert(get_father(s1[i]));
		}
		if(s2.size() > 1) flag = false;
		if(flag) puts("Yes");
		else puts("No");
	}
}

M - Is It A Tree?

题意:
判断输入是否符合一棵树的定义,树也可以是空树,因此,0 0也是一颗树。

//
//Write by Yuan Xilan on 2019...
//
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<string>
#include<iostream>
#include<sstream>
#include<set>
#include<map>
#include<queue>
#include<bitset>
#include<vector>
#include<limits.h>
#include<assert.h>
#define SZ(X) ((int)(X).size())
#define ALL(X) (X).begin(), (X).end()
#define REP(I, N) for (int I = 0; I < (N); ++I)
#define REPP(I, A, B) for (int I = (A); I < (B); ++I)
#define FOR(I, A, B) for (int I = (A); I <= (B); ++I)
#define FORS(I, S) for (int I = 0; S[I]; ++I)
#define RS(X) scanf("%s", (X))
#define SORT_UNIQUE(c) (sort(c.begin(),c.end()), c.resize(distance(c.begin(),unique(c.begin(),c.end()))))
#define GET_POS(c,x) (lower_bound(c.begin(),c.end(),x)-c.begin())
#define CASET int ___T; scanf("%d", &___T); for(int cs=1;cs<=___T;cs++)
#define MP make_pair
#define PB push_back
#define MS0(X) memset((X), 0, sizeof((X)))
#define MS1(X) memset((X), -1, sizeof((X)))
#define LEN(X) strlen(X)
#define F first
#define S second
using namespace std;
typedef long long ll,LL;
typedef unsigned long long ull;
typedef long double ld;
typedef pair<int,int> PII;
typedef vector<int> VI;
typedef vector<LL> VL;
typedef vector<PII> VPII;
typedef pair<LL,LL> PLL;
typedef vector<PLL> VPLL;
void R() {}
#ifdef HOME
 #define DEBUG(...) {printf("# ");printf(__VA_ARGS__);puts("");}
#else
 #define DEBUG(...)
#endif
const int maxn = 134567;
int father[maxn];
int src[maxn];
int n,m,t,times;
bool flag = true;

void init(){
	for(int i=1; i<=134555; ++i){
		father[i] = i;
	}
}

int get_father(int x){
	if(father[x] == x) return x;
	return father[x] = get_father(father[x]);
}

void merge(int x, int y){
	x = get_father(x);
	y = get_father(y);
	if(x != y){
		father[x] = y;
	}
	else flag = false;
}

int main(){
	
	while(cin >> n >> m){
		if(n == 0 && m == 0){
			cout << "Case " << ++times << " is a tree." << endl;
			continue;
		}
		vector<int>s1;
		set<int>s2;
		flag = true;
		init();
		if(n == -1 && m == -1) break;
		merge(n, m);
		s1.push_back(n);
		s1.push_back(m);
		while(1){
			cin >> n >> m;
			if(n == 0 && m == 0) break;
			s1.push_back(n);
			s1.push_back(m);
			merge(n, m);
		}
		for(int i=0; i<s1.size(); ++i){
			s2.insert(get_father(s1[i]));
		}
		if(s2.size() > 1) flag = false;
		cout << "Case " << ++times << " is";
		if(!flag) cout << " not";
		cout << " a tree.\n";	
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值