BestCoder Round #71 (div.1)题解

本文针对BestCoderRound#71(div.1)中的1004题提供了详细的解析,介绍了如何利用最小生成树的概念解决实际问题。文章深入探讨了在特定条件下寻找最优道路建设方案的方法,并通过枚举最小边的方式逐步优化解决方案,最终给出了一种高效的算法实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

BestCoder Round #71 (div.1)

1004 题目描述

我们可爱的KK有一道困难的社会性题目:他所在的地区发生了一场大地震(如此老套的出题思路~!),一共有N( 2<= N<= 2000)个城市受到了牵连,N个城市间所有道路都已损坏,现在KK受委托要重修这些道路。然而,经过KK的实地考察发现,很多城市间道路的地基都被破坏了,无法再重修道路,因此可供修建的道路只有MM(0≤M≤15000)条。KK要用尽量少的道路将所有的城市联通起来,在此条件下,他希望选择一种方案,使得方案中最贵道路的价格和最便宜道路的价格的差值最小。

思路

BC的题解上写了这么一句:

我们知道,最小生成树有一个性质是最大边最小。

我咋就不知道这个!(其实就是离散没学好)
有了这句话,我们就可以枚举最小边,这样的生成树一定包含答案,再进行一点优化:

引用http://bestcoder.hdu.edu.cn/

可以发现我们每次枚举后都重新求了最小生成树,事实上这是不必要的。

考虑从大到小枚举生成树的最小边,我们要做的实际上是每次加入一条边,维护当前图的最小生成树。

加入一条边时,我们需要判断这条边能否与之前的边构成环。

  • I 若能构成环,用该边替代环中最大边一定更优;
  • II 若不能构成环,直接加入该边即可。

以上是BC题解写的一部分,找环中最大边用DFS实现,但是目前我还是没有思路。

====================(我是分割线)3分钟后================

应该是直接暴力DFS就好,生成树里边数为N-1,所以DFS的时间复杂度为O(N),枚举最小边这样时间复杂度为O(MlogM(快排)+NM)

### Codeforces Round 260 Div. 1 题目及题解 #### A. Vasya and Multisets 在这道题目中,Vasya有一个由n个整数组成的序列。目标是通过将这些数分成若干组,使得每组中的所有数都相同,并且尽可能减少分组的数量。 为了实现这一目的,可以利用贪心算法来解决这个问题。具体来说,在遍历输入数据的同时维护当前最大频率计数器,对于每一个新遇到的不同数值增加一个新的集合[^1]。 ```cpp #include <bits/stdc++..h> using namespace std; void solve() { int n; cin >> n; unordered_map<int, int> freq; for (int i = 0; i < n; ++i) { int x; cin >> x; freq[x]++; } int maxFreq = 0; for (auto& p : freq) { maxFreq = max(maxFreq, p.second); } cout << maxFreq << "\n"; } ``` #### B. Pashmak and Graph 此问题涉及图论领域的一个经典最短路径计算案例。给定一张带权无向图以及起点S和终点T,要求求出从S到T经过至少一条边后的最小花费总和。 Dijkstra算法适用于此类场景下的单源最短路径查询任务。初始化距离表dist[]为无穷大(INF),仅设置起始节点的距离为零;随后借助优先队列选取未访问过的最近邻接顶点u更新其相邻结点v至目前为止所知的最佳到达成本min{dist[u]+w(u,v)}直至找到终止条件即抵达目的地t或处理完毕所有可达区域内的候选者为止。 ```cpp typedef pair<long long,int> pli; const long long INF = LLONG_MAX / 3; struct Edge { int to, cost; }; vector<Edge> G[MAX_V]; long long d[MAX_V]; bool dijkstra(int s, int t){ priority_queue<pli,vector<pl>,greater<pl>> que; fill(d,d+MAX_V,INF); d[s]=0; que.push(pli(0,s)); while(!que.empty()){ pli p=que.top();que.pop(); int v=p.second; if(d[v]<p.first) continue; for(auto e:G[v]){ if(d[e.to]>d[v]+e.cost){ d[e.to]=d[v]+e.cost; que.push(pli(d[e.to],e.to)); } } } return d[t]!=INF; } ``` #### C. DZY Loves Colors 这是一道关于颜色染色的问题。给出长度为N的一维网格,初始状态下每个格子都有一个默认的颜色编号。现在有M次操作机会改变某些位置上的色彩值,最终目的是统计整个条带上共有几种不同的色调存在。 采用离散化技术预处理原始输入并记录下各段连续同色区间的端点坐标范围,之后针对每一次修改请求动态调整受影响部分的信息结构体(如线段树),最后依据累积的结果得出答案。 ```cpp // 假设已经实现了上述提到的数据结构 SegmentTree 和 update 函数 SegmentTree st; for(int i=1;i<=m;++i){ int l,r,c; scanf("%d%d%d",&l,&r,&c); update(l,r,c); } printf("%lld\n",st.query()); ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值