Codeforces 1245D Shichikuji and Power Grid

思路:

这题一共有两种思路:
1.设立一个虚点,将所有点和它连接,costci,然后其它点两两相连,cost为两点之间建立连接所需价格,然后求这个图的最小生成树,求出来的树中,和虚点相连的点就是自己设发电站的点,两个顶点都不是虚点的边就是需要修路的边;(在求解过程中需要使用long long
2.由贪心思想可以得知,所有ci中最小的那个i点一定要设立发电站,此时我们遍历所有j>=1&&j<=n&&j!=i,这时j有两种选择:(1)和i相连 (2)自己建发电站;我们在这两种里面选择花费最小的那一种并更新cj,并记录更小的情况是自己建站还是和i连接(只是更新cj,还未决定到底是自己建or连接ior连接其它点),全部更新一遍之后,我们再在所有未建发电站的点里选取c最小的那一个,对它通电(是自己建站还是进行连接,就根据之前的记录),然后依次循环到所有点通电就ok了~(因为笔者只实现了最小生成树,这种贪心方法没有贴出代码,所以我就稍微啰嗦一点了QAQ)

代码:

#define IOS ios::sync_with_stdio(false);cin.tie(0)
#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> P;
typedef long long LL;
#define fi first
#define sc second
#define pb(a) push_back(a)
#define mp(a,b) make_pair(a,b)
#define rp(i,n) for(int i=0;i<n;i++)
#define rpn(i,n) for(int i=1;i<=n;i++)
const int MAX_N=2000+99; 
int par[MAX_N],rank_u[MAX_N];  //MAX_N集合里最多元素个数
void init_union(int n){
	for(int i=0;i<n;i++){
		par[i]=i;
		rank_u[i]=0;
	}
}
int find(int x){
	if(par[x]==x) return x;
	else return par[x]=find(par[x]);
}
void unite(int x,int y){
	x=find(x);
	y=find(y);
	if(x==y) return;
	if(rank_u[x]<rank_u[y]) par[x]=y;
	else{
		par[y]=x;
		if(rank_u[x]==rank_u[y]) rank_u[x]++;
	}
}
bool same(int x,int y){
	return find(x)==find(y);
}
struct edge{int u,v;LL cost;};
bool cmp(const edge& e1,const edge& e2){
	return e1.cost<e2.cost;
}
const int MAX_E=2001000+99;
edge es[MAX_E];
int V,E;//顶点数和边数
vector<int> v1;//自己建发电站
vector<P> v2;//连接别的发电站 
LL kruskal(){
	sort(es,es+E,cmp);
	init_union(V);
	LL res=0;
	for(int i=0;i<E;i++){
		edge e=es[i];
		if(!same(e.u,e.v)){
			if(e.u&&e.v) v2.pb(mp(e.u,e.v));
			else v1.pb(e.u?e.u:e.v);
			unite(e.u,e.v);
			res+=e.cost;
		}
	}
	return res;
}
P cod[MAX_N];
LL K[MAX_N];
LL cost(int a,int b){return (K[a]+K[b])*(abs(cod[a].fi-cod[b].fi)+abs(cod[a].sc-cod[b].sc));}
int main(){
	IOS;
	int n;
	cin>>n;
	V=n+1; E=(n+1)*n/2;
	rpn(i,n) cin>>cod[i].fi>>cod[i].sc;
	int pos=0;
	rpn(i,n){
		LL cost;
		cin>>cost;
		es[pos++]=edge{0,i,cost};
	}
	rpn(i,n) cin>>K[i];
	for(int i=1;i<n;i++){
		for(int j=i+1;j<=n;j++) es[pos++]=edge{i,j,cost(i,j)};
	}
	cout<<kruskal()<<'
';
	cout<<v1.size()<<'
'<<v1[0];
	for(int i=1;i<v1.size();i++) cout<<' '<<v1[i];
	cout<<'
'<<v2.size()<<'
';
	rp(i,v2.size()) cout<<v2[i].fi<<' '<<v2[i].sc<<'
';
	return 0;
}
原文地址:https://www.cnblogs.com/yuhan-blog/p/12308846.html