城市聚集度_200分_A/B卷复用_并查集

城市聚集度

题目描述:

  一张地图上有n个城市,城市和城市之间有且只有一条道路相连:要么直接相连,要么通过其它城市中转相连(可中转一次或多次)。
  城市与城市之间的道路都不会成环
  当切断通往某个城市i的所有道路后,地图上将分为多个连通的城市群,设该城市的聚集度为DPi (Degree of Polymerization),
    DPi= max (城市群1的城市个数,城市群2的城市个数,…城市群 m 的城市个数)
请找出地图上 DP值Q最小 的城市 (即找到城市,使得DPi = min(DP1.DP2…DPn)

提示:
  如果有多个城市都满足条件,这些城市都要找出来 (可能存在多个解)提示:DPi的计算,可以理解为已知一棵树,删除某人节点后;生成的多个子树,求解多人子数节点数的问题.

输入输出描述:

输入描述:

  第一行有一个整数N,表示有N个节点。1 <= N <= 1000。
  接下来的 N-1 行每行有两个整数x,y,表示城市x与城市y连接。1<= x,y<= N

输出描述:

  输出城市的编号。如果有多个,按照编号升序输出。

示例1:

输入:
	5
	1 2
	2 3
	3 4
	4 5
输出:
	3
说明:
	切断通往1的所有道路后,形成的城市群为{{2,3,4,5}},其聚集度:DP1=4
	切断通往2的所有道路后,形成的城市群为{{1}, {3,4,5}},其聚集度: DP2=max(1, 3)=3
	切断通往3的所有道路后,形成的城市群{{1, 2}, {4,5}},其聚集度:DP3 = max(2, 2)= 2。
	切断通往4的所有道路后,形成的城市群{{1, 2, 3}, {5},其聚集度:DP4 = max(3,1)= 3。
	切断通往5的所有道路后,形成的城市群{{1, 2, 3, 4},其聚集度:DP5 = 4
	故切断通往3时,聚集度最小,故输出是3。

示例1:

输入:
	6
	1 2
	2 3
	2 4
	3 5
	3 6
输出:
	2 3
说明:
	将通往2或者3的所有路径切断,最大城市群数量是3,
	其他任意城市切断后,最大城市群数量都比3大,
	所以输出2 3。

解题思路:

以示例1为例,分析过程如下图所示:
示例1的指示图
题意:共有 n 个城市编号为[1, n],每个每个点都和其他点直接或者间接相连,要求找到某个 点 i,断开与该点直接相连的线,这样c,除了 点i 以外,其余的城市就会形成1个或多个相互独立的城市集群,记录下城市数量点最少的城市集群数量和该 点i 即可。
解题思路:
因为需要每个点都尝试,所以需要进行一次循环,断开每个 点i 与其他点的连接;
断开了 点i 之后,对剩余的 n - 1 个点进行分类(即之间相连或者间接相连的点属于同一个集群/类别——并查集)

代码:

// 路径压缩的加权quick-union算法模板
static class UF {
	// 记录集群代表元
	int[] parent;
	// 记录该集群中的元素个数
	int[] size;
	// 标记最大的一个集群的所包含节点数量
	int maxUFCount;
	// 标记一共有多少个相互独立的集群
	int unionCount;

	private UF (int n) {
		parent = new int[n + 1];
		size = new int[n + 1];
		maxUFCount = 1;
		unionCount = n;

		for (int i = 0; i <= n; i++) {
			parent[i] = i;
			size[i] = 1;
		}
	}

	// 获取最大集群包含的节点个数
	public int getMaxUFCount() {
		return maxUFCount;
	}
	
	// 获取相互独立的集群数量
	public int getUnionCount() {
		return unionCount;
	}

	// 合并两个点所在的集群
	public void union (int a, int b) {
		int rootA = find(a);
		int rootB = find(b);

		if (rootA != rootB) {
			if (size[rootA] < size[rootB]) {
				parent[rootA] = rootB;
				size[rootB] += size[rootA];
				// 更新最大个集群包含节点数量
				maxUFCount = Math.max(maxUFCount, size[rootB]);
			} else {
				parent[rootB] = rootA;
				size[rootA] += size[rootB];
				// 更新最大个集群包含节点数量
				maxUFCount = Math.max(maxUFCount, size[rootA]);
			}
			// 合并了两个集群,则集群数量 -1
			unionCount--;
		}
	}

	// 查找某个点的代表元是哪个
	private int find (int p) {
		if (parent[p] == p) {
			return p;
		}
		
		// 路径压缩
		return parent[p] = find(parent[p]);
	}
}

public static void main(String[] args) {
	// 读取数据
	Scanner in = new Scanner(System.in);
	int n = in.nextInt();
	int[][] arr = new int[n][2];
	int[] memo = new int[n + 1];
	int min = Integer.MAX_VALUE;

	for (int i = 0; i < n - 1; i++) {
		arr[i][0] = in.nextInt();
		arr[i][1] = in.nextInt();
	}

	// 1~n这些点
	for (int i = 1; i <= n; i++) {
		// 遍历输入的所有边,并剔除掉包含当前点的边——即隔断该点与其他点的连接
		UF uf = new UF(n);
		for (int j = 0; j < n; j++) {
			if (arr[j][0] != i && arr[j][1] != i) {
				uf.union(arr[j][0], arr[j][1]);
			}
		}

		// 剔除掉点 i 之后形成的孤立的城市群中,最大的城市集包含节点数为
		memo[i] = uf.getMaxUFCount();
		min = Math.min(min, memo[i]);
	}

	// 输出答案
	StringBuilder stringBuilder = new StringBuilder();
	for (int i = 1; i <= n; i++) {
		if (memo[i] == min) {
			stringBuilder.append(i + " ");
		}
	}

	System.out.println("最小:" + min);
	System.out.println(stringBuilder.toString());
}

并查集相关题目

发广播_200分_A/B卷复用_并查集/dfs
快递业务站_100分_2023A卷_并查集/dfs

并查集模板代码

// 路径压缩的加权quick-union算法模板
static class UF {
	// 记录集群代表元
	int[] parent;
	// 记录该集群中的元素个数
	int[] size;
	// 标记最大的一个集群的所包含节点数量
	int maxUFCount;
	// 标记一共有多少个相互独立的集群
	int unionCount;

	private UF (int n) {
		parent = new int[n + 1];
		size = new int[n + 1];
		maxUFCount = 1;
		unionCount = n;

		for (int i = 0; i <= n; i++) {
			parent[i] = i;
			size[i] = 1;
		}
	}

	// 获取最大集群包含的节点个数
	public int getMaxUFCount() {
		return maxUFCount;
	}
	
	// 获取相互独立的集群数量
	public int getUnionCount() {
		return unionCount;
	}

	// 合并两个点所在的集群
	public void union (int a, int b) {
		int rootA = find(a);
		int rootB = find(b);

		if (rootA != rootB) {
			if (size[rootA] < size[rootB]) {
				parent[rootA] = rootB;
				size[rootB] += size[rootA];
				// 更新最大个集群包含节点数量
				maxUFCount = Math.max(maxUFCount, size[rootB]);
			} else {
				parent[rootB] = rootA;
				size[rootA] += size[rootB];
				// 更新最大个集群包含节点数量
				maxUFCount = Math.max(maxUFCount, size[rootA]);
			}
			// 合并了两个集群,则集群数量 -1
			unionCount--;
		}
	}

	// 查找某个点的代表元是哪个
	private int find (int p) {
		if (parent[p] == p) {
			return p;
		}
		
		// 路径压缩
		return parent[p] = find(parent[p]);
	}
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
#include "driverlib.h" #define TIMER_PERIOD 8192 void Timer_A0_PWM_Init(void) { Timer_A_outputPWMParam htim = {0}; //P1.2复用输出 GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P1, GPIO_PIN2); //时钟源选为SMCLK = 1048576 HZ htim.clockSource = TIMER_A_CLOCKSOURCE_SMCLK; //频系数设为32 32768HZ htim.clockSourceDivider = TIMER_A_CLOCKSOURCE_DIVIDER_32; //装载值设为8192 - 1 ,周期为0.25s htim.timerPeriod = TIMER_PERIOD - 1; //P1.2 对应 TA0.1 故设为TIMER_A_CAPTURECOMPARE_REGISTER_1 定时器为0 htim.compareRegister = TIMER_A_CAPTURECOMPARE_REGISTER_1; //选择复位置位模式 htim.compareOutputMode = TIMER_A_OUTPUTMODE_RESET_SET; //设置占空比,为5% htim.dutyCycle = TIMER_PERIOD / 20 ; //P1.2 对应 TA0.1 为TIMER_A0_BASE Timer_A_outputPWM(TIMER_A0_BASE, &htim); } void Timer_A1_PWM_Init(void) { Timer_A_outputPWMParam htim = {0}; //P1.3复用输出 GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P1, GPIO_PIN3); //时钟源选为SMCLK = 1048576 HZ htim.clockSource = TIMER_A_CLOCKSOURCE_SMCLK; //频系数设为32 32768HZ htim.clockSourceDivider = TIMER_A_CLOCKSOURCE_DIVIDER_32; //装载值设为8192 - 1 ,周期为0.25s htim.timerPeriod = TIMER_PERIOD - 1; //P1.3 对应 TA1.1 故设为TIMER_A_CAPTURECOMPARE_REGISTER_1 定时器为1 htim.compareRegister = TIMER_A_CAPTURECOMPARE_REGISTER_1; //选择复位置位模式 htim.compareOutputMode = TIMER_A_OUTPUTMODE_RESET_SET; //设置占空比,为10% htim.dutyCycle = TIMER_PERIOD / 10 ; //P1.3 对应 TA1.1 为TIMER_A1_BASE Timer_A_outputPWM(TIMER_A1_BASE, &htim); }
07-16

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值