洛谷 P1194 买礼物 最小生成树--但有小坑

这个题我们模拟题目一下就会发现是一道最小生成树的题目,

我们通常会想到:ans=最小生成树的长度+单买一件商品a

注意点1:如果 KI,J​=0,那么表示这两样东西之间不会导致优惠。也就是没有边

注意点2:注意 KI,J​ 可能大于 A。这就意味着我们需要 min(ans,a*b)一下

不过还有一个坑点(我忽略了):可能不连通(也就是没有最小生成树),这种情况就用现有的(假)最小生成树+要单买的商品+a


const int N = 500 + 10,T = 20;


LL a,b;

struct Edge
{
	LL a,b,w;
	bool operator< (const Edge& t) const
	{
		return w < t.w;
	}
};


int p[N];
vector<Edge> edges;

LL find(LL x)
{
	if (p[x] != x) p[x] = find(p[x]);
	return p[x];
}

void solve()
{
	cin >> a >> b;
	for (int i = 1;i <= b;i ++)
		for (int j = 1;j <= b;j ++)
		{
			LL w; cin >> w;
			if (i != j && !w) continue;
			edges.push_back({i,j,w});
		}
	
	sort(edges.begin(),edges.end());
	
	for (int i = 1;i <= b;i ++) p[i] = i;
	
	LL ans = 0;
	LL cnt = 0;
	for (auto &[a,b,w] : edges)
	{
		if (find(a) == find(b)) continue;
		ans += w;
		p[find(a)] = find(b);
		cnt ++;
	}
	
	if (cnt == b - 1)//联通
		cout << min(ans + a,a * b) << endl;
	else//不连通
		cout << min(ans + (b - 1 - cnt) * a + a,a * b) << endl;
}	






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值