Destroy Walls(思维+最大生成树)

Link

题意

给出 n 个城市的坐标 xi,yi,有 m 个城墙,第 ui 个城市和第 vi 个城市之间是一道城墙(ui 不能直接到达vi),破坏该城墙需要 wi 的花费,问使得使整个图联通的最小花费。

思路

如果一个区域与另外一个区域无法联通那么其一定被城墙环绕, 我们只需要拆掉其最小的权值的那个边就好了, 也就是把所有的环变成一颗树或者多棵树就好了, 至于没用到的边就是需要拆掉的边

细节见于代码

#include <bits/stdc++.h>

using namespace std;

const int N = 1e5 + 10;
int n, m;
struct node
{
	int x, y, s;
	bool operator <(const node &t) const
	{
		return s > t.s;
	}
};
int fa[N];

int find_(int x)
{
	return x == fa[x] ? x: fa[x] = find_(fa[x]);
}
int main()
{
	while(~scanf("%d%d", &n, &m))
	{
		for(int i = 1; i <= n; i++)
		{
			int x, y;
			scanf("%d%d", &x, &y);
			fa[i] = i;
		}
		vector<node> v;
		int all = 0;
		for(int i = 1; i <= m; i ++)
		{
			int x, y, z;
			scanf("%d%d%d", &x, &y, &z);
			v.push_back({x, y, z});
			all += z;
		}
		sort(v.begin(), v.end());
		int sum = 0;
		int ans = 0;
		for(int i = 0; i < m; i++)
		{
			int x = v[i].x, y = v[i].y;
			int x1 = find_(x), y1 = find_(y);
			if(x1 != y1)
			{
				fa[x1] = y1;
				ans ++;
				sum += v[i].s;
			}
		}
		int x = 1;
		printf("%d %d\n", m - ans, all - sum);
	}
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值