并查集(DSU)

#include<stdio.h>

int parent[10001];

int findParent(int x, int parent[]) {	//找最终根节点
	int xRoot = x;
	while (parent[xRoot] != -1) {
		xRoot = parent[xRoot];
	}
	return xRoot;
}

void unionXY(int x, int y, int parent[]) {	//连接两个节点的最终根节点
	int xRoot = findParent(x, parent);
	int yRoot = findParent(y, parent);
	if (xRoot != yRoot) {		//未连接
		parent[xRoot] = yRoot;
	}
}

int judgeUnion(int x, int y, int parent[]) {	//判断两个节点是否连接	1-是 0-否
	int xRoot = findParent(x, parent);
	int yRoot = findParent(y, parent);
	if (xRoot == yRoot) {
		return 1;
	}
	else
	{
		return 0;
	}
}

int connectedAreaNum(int N, int parent[]) {		//计算连通集个数
	int i, j;
	int tempRoot = 0;
	int areaNum[1000];	//连通集
	int lengthArea = 0;
	for (i = 1; i <= N; i++) {
		tempRoot = findParent(i, parent);
		for (j = 0; j < lengthArea; j++) {
			if (areaNum[j] == tempRoot) {
				break;
			}
		}
		if (j == lengthArea) {
			areaNum[lengthArea] = tempRoot;
			lengthArea++;
		}
	}
	return lengthArea;
}


int main() {
	int x, y, N, i, j, temp;
	memset(parent, -1, sizeof(parent));
	printf("请输入网络中计算机的总台数:");
	scanf("%d", &N);
	getchar();
	if (N <= 0) {
		return 0;
	}
	char select;
	printf("请输入操作:(|-连接,C-检查,S-结束):");
	scanf("%c", &select);
	while (1)
	{
		switch (select)
		{
		case '|':
			printf("请输入两个待连接计算机序号(1-C1,2-C2,以此类推):\n");
			scanf("%d%d", &x, &y);
			unionXY(x, y, parent);
			printf("\t连接成功!\n\n");
			break;
		case 'C':
			printf("请输入两个待检查计算机序号(1-C1,2-C2,以此类推):\n");
			scanf("%d%d", &x, &y);
			if (judgeUnion(x, y, parent)) {
				printf("\tyes\n\n");
			}
			else
			{
				printf("\tno\n\n");
			}
			break;
		case 'S':
			if (connectedAreaNum(N, parent) == 1) {
				printf("\tThe network is connected.\n\n");
			}
			else
			{
				printf("\tThere are %d components.\n\n", connectedAreaNum(N, parent));
			}
			return 0;
		default:
			printf("\t输入错误,请重新输入!\n\n");
			break;
		}
		getchar();
		printf("请输入操作(|-连接,C-检查,S-结束):");
		scanf("%c", &select);
	}

	return 0;
}

例图:

 

测试结果:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值