最小生成树

这篇博客介绍了一种使用贪心策略求解最小生成树的方法,具体是通过找到一个中心点(如0点),然后逐步加入与其距离最近的点来构建树。在ACWING平台的3728题中,该策略被应用到多个点可选为中心的场景,计算建立发电站的最小成本。博客提供了详细的算法实现,包括Prim算法的优化,并给出了输出最小生成树边的路径。

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

贪心策略,随便找一个点一般为1,每次找到与其最近的点加入树,同时对加入的点记忆化,之后更新每个最近的值并用pre记录前驱,(可以打印边与路径);
变形:
对于下面这种对个点可以做中心(如建立发电站)求最小生成树的,找到0点作为超级点,到每个中心的w即建立发电站的费用,将0点加入,求最小生成树即可。
原题:ACWING,3728

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<set>
#include<string.h>
#include<vector>
#include<set>
#include<cmath>
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define ll long long
#define inf 0x3f3f3f3f
#define x first
#define y second
using namespace std;
const int N=2010;
typedef pair<int,int> PII;
ll dist[N];
 int distp[N];
vector<int>ans1;
vector<PII>ans2;
PII a[N];
bool su[N];
int wc[N],wk[N];
int n;
inline ll get_disw(int i,int j)
{
    int dx=a[i].x-a[j].x;
    int dy=a[i].y-a[j].y;
    return (ll)(abs(dx)+abs(dy))*(wk[i]+wk[j]);
}
ll prim()
{
    su[0]=true;
    dist[0]=0;
    ll res=0;
    for(int i=1;i<=n;i++)dist[i]=wc[i];
    for(int i=0;i<n;i++)
    {
        int t=-1;
        for(int j=1;j<=n;j++)
        {
            if(!su[j]&&(t==-1||dist[t]>dist[j]))
            {
                t=j;
            }
        }
        su[t]=true;
        res+=dist[t];
        if(distp[t]==0)ans1.push_back(t);
        else ans2.push_back({distp[t],t});
        for(int j=1;j<=n;j++)
        {
            if(!su[j]&&dist[j]>get_disw(j,t))
            {
                dist[j]=get_disw(j,t);
                distp[j]=t;
            }
        }
    }
    return res;
}
int main()
{
    cin>>n;
    for(int i=1;i<=n;i++)cin>>a[i].x>>a[i].y;
    for(int i=1;i<=n;i++)cin>>wc[i];
    for(int i=1;i<=n;i++)cin>>wk[i];
    ll res=prim();
    printf("%lld\n",res);
    printf("%d\n",ans1.size());
    for(auto m: ans1)printf("%d ",m);
    puts("");
    printf("%d\n",ans2.size());
    for(auto& g: ans2)printf("%d %d\n",g.x,g.y);
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值