题目链接
题意:一开始有n个城市都是没有通电的(以坐标形式给出),如果要给城市i设通电要花费ci,假设a城市有电,给城市a和b建一条建边,那么b也会从没电变有电,花费为他们坐标的曼哈顿距离,求给所有城市通电的最小花费。
思路:我们建立一个超级源点0,0到城市i的边权为ci,然后再构造一个完全图,将各个点进行连边,然后求一下最小生成树就是答案了。
#include<bits/stdc++.h>
using namespace std;
const int maxn=2e3+10;
typedef long long ll;
struct node{
ll U,V,dis;
};
int n,father[maxn],cnt=0;
ll sum=0,c[maxn],k[maxn],x[maxn],y[maxn];
vector<int>ans;
vector<node>v;
vector<pair<int,int>>temp;
bool cmp(const node &a,const node &b)
{
return a.dis<b.dis;
}
int findfather(int x)
{
if(x==father[x]) return x;
int i=findfather(father[x]);
father[x]=i;
return i;
}
int main()
{
scanf("%lld",&n);
for(int i=0;i<=n;++i) father[i]=i;
for(int i=1;i<=n;++i) scanf("%lld%lld",&x[i],&y[i]);
for(int i=1;i<=n;++i) scanf("%lld",&c[i]);
for(int i=1;i<=n;++i) scanf("%lld",&k[i]);
for(int i=1;i<=n;++i)
for(int j=i+1;j<=n;++j)
v.push_back({i,j,1ll*(k[i]+k[j])*(abs(x[i]-x[j])+abs(y[i]-y[j]))});
for(int i=1;i<=n;++i) v.push_back({0,i,c[i]});
sort(v.begin(),v.end(),cmp);
for(int i=0;i<v.size();++i)
{
int fa=findfather(v[i].U),fb=findfather(v[i].V);
if(fa!=fb)
{
father[fa]=fb;
if(v[i].U==0) ans.push_back(v[i].V);
else temp.push_back({v[i].U,v[i].V});
sum+=v[i].dis;
cnt++;
if(cnt==n) break;
}
}
cout<<sum<<endl;
cout<<ans.size()<<endl;
for(int i=0;i<ans.size();++i) cout<<ans[i]<<" ";
cout<<endl;
cout<<temp.size()<<endl;
for(int i=0;i<temp.size();++i) cout<<temp[i].first<<" "<<temp[i].second<<endl;
}