[题解]P5687 [CSP-S2019 江西] 网格图

P5687 [CSP-S2019 江西] 网格图

简单来说题目就是给定一个\(n\times m\)的网格图,同行边权相同,同列边权相同,求该网格图的最小生成树。

根据Kruskal算法的贪心思想,我们要优先选择权值尽可能小的行,并将这条边应用于尽可能多的列。列方向同理。

为了保证最终生成树的连通性,我们显然要先把最小的行和最小的列全都选上,如下图所示:

可以发现,如果当前已经选择了\(x\)组行方向上的边,此时如果选列方向上的边,则最多能放\(n-x\)条。列方向同理。

根据贪心思想,接下来我们选择第\(3\)行,此时我们最多能放\(8-1=7\)条边,将其全部选择。

根据贪心思想,接下来我们选择第\(6\)列(或第\(2\)列),此时我们最多能放\(5-2=3\)条边,将其全部选择。
我们发现最多只能放\(3\)条,否则一定会出现环。
……

有了上面的结论,我们就可以写出代码了。将行和列的权值分别排序,先各选去一个最小值,再用两个指针分别指向两个数组的第\(2\)为,每次选权值最小的行/列即可。

点击查看代码
#include<bits/stdc++.h>
#define int long long
#define N 300010
using namespace std;
int n,m,a[N],b[N],posa,posb,ans,cnt;
signed main(){
cin>>n>>m;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<=m;i++) cin>>b[i];
sort(a+1,a+1+n);
sort(b+1,b+1+m);
posa=1,posb=1;
ans=a[1]*(m-1)+b[1]*(n-1),cnt=n+m-2;
while(1){
if(a[posa+1]<b[posb+1]){
ans+=a[++posa]*(m-posb),cnt+=(m-posb);
}else{
ans+=b[++posb]*(n-posa),cnt+=(n-posa);
}
if(cnt==n*m-1) break;
}
cout<<ans<<"\n";
return 0;
}
posted @   Sinktank  阅读(8)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
2025-3-6 6:10:37 TOP-BOTTOM-THEME
Enable/Disable Transition
Copyright © 2023 ~ 2024 Sinktank - 1328312655@qq.com
Illustration from 稲葉曇『リレイアウター/Relayouter/中继输出者』,by ぬくぬくにぎりめし.
点击右上角即可分享
微信分享提示