(最小生成树)洛谷P2916 [USACO08NOV]安慰奶牛Cheering up the Cow

本文介绍了如何应用最小生成树算法解决USACO竞赛中的‘安慰奶牛’问题。通过分析,作者发现需要对点权和边权进行预处理。首先尝试将点权加入边权,但这种方法只适用于部分情况。接着,作者将节点分为起点、叶子和中间点三类,并建立了新的模型。在新的模型中,叶子节点的度数为1,中间节点的度数等于经过次数。通过将边权变为原来的2倍并加上起点和终点的权值,构建最小生成树。最后,加上点权最小的点作为起点的额外谈话次数,即可得到最小谈话时间。代码部分提供了实现细节和注释。
摘要由CSDN通过智能技术生成

一、算法分析

刚看到题的时候没什么头绪,然后先模拟了一下题上的例子,感觉本题基本框架还是最小生成树,但是需要预处理一下,刚开始的想法是把点权加到边权上面,好能求最小生成树。然后开始的实现方式就是把每个边的边权加上这个边的起点的点权,样例也能过。但是交上去之后只能过第一个点。说明这样的方法不对,那么就需要建模求解正确方法,建模时将点分为三类,起点(根)、叶子、中间点。可以证明在一个生成树中,根据题目中的走法,叶子的度数为1,且经过一次,中间点的度数等于其经过次数,叶子和中间点这两类点可以合并,但是起点会多经过(谈话)一次,然后每条边会经过两次。如果先不算起点多的那次的话,新的边权就可以设置成原来边权乘2再加上边的起点和终点权值,然后跑一遍最小生成树,把最小生成树上所有边权加起来即可。然后再算多起点多出来的那一次,因为起点是可以自定的,所以要想谈话时间最小,那就可以把点权最小的点作为起点。所以最终答案就是最小生成树中,预处理后的新边权和再加上最小点权。

二、代码及注释

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define ll long long
using namespace std;
const int maxn=10050;            
int pa[maxn];
int r[maxn];
int n,m;
int findy(int x){
                              //并查集板子 
	if(x==pa[x]) return x;
	int root=findy(pa[x]);
	return pa[x]=root;
} 
bool pd(int x,int y){
   
	int xx=findy(x
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值