思路:一个很裸的最小生成树。把建立基站看成是,城市与源点(虚构的)建边。由此建立最小生成树,即可得出答案。
代码:
// Created by CAD on 2019/11/2.
#include <bits/stdc++.h>
#define ll long long
#define pii pair<int,int>
using namespace std;
const int maxn=2020*2000;
struct edge{
ll u,v;
ll w;
bool operator<(edge &e)
{
return w<e.w;
}
}e[maxn];
ll fa[2005],x[2005],y[2005],c[2005],k[2005];
int n;
vector<int> out1;
vector<pii> out2;
int find(int i)
{
return i==fa[i]?i:fa[i]=find(fa[i]);
}
int cnt=0;
int cnt1=0;
ll kruskal()
{
ll ans=0;
for(int i=0;i<=n;++i)
fa[i]=i;
for(int i=1;i<=cnt;++i)
{
int u=find(e[i].u),v=find(e[i].v);
if(u!=v)
{
ans+=e[i].w,fa[v]=u;
if(!e[i].u) out1.push_back(e[i].v);
else out2.push_back({e[i].u,e[i].v});
}
}
return ans;
}
int main()
{
// FOPEN;
ios::sync_with_stdio(false);
cin.tie(0);
cin>>n;
for(int i=1;i<=n;++i)
cin>>x[i]>>y[i];
for(int i=1;i<=n;++i)
cin>>c[i];
for(int i=1;i<=n;++i)
cin>>k[i];
for(int i=1;i<=n;++i)
e[++cnt]=edge{0,i,c[i]};
for(int i=1;i<=n;++i)
for(int j=i+1;j<=n;++j)
e[++cnt]=edge{i,j,1ll*(abs(x[i]-x[j])+abs(y[i]-y[j]))*(k[i]+k[j])};
sort(e+1,e+cnt+1);
cout<<kruskal()<<endl;
cnt1=out1.size();
cout<<cnt1<<endl;
for(int i=0;i<cnt1-1;++i)
cout<<out1[i]<<" ";
if(cnt1)
cout<<out1[cnt1-1]<<endl;
cout<<out2.size()<<endl;
for(auto i:out2)
cout<<i.first<<" "<<i.second<<endl;
return 0;
}
原文地址:https://www.cnblogs.com/CADCADCAD/p/11782455.html
时间: 2024-10-08 09:34:28