Codeforces Round #597 (Div. 2) D. Shichikuji and Power Grid(最小生成树)

题目链接
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
题意:一开始有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; 
}
发布了111 篇原创文章 · 获赞 0 · 访问量 4004

猜你喜欢

转载自blog.csdn.net/qq_42479630/article/details/104434538