Daniel and Spring Cleaning
给出城市x,y坐标,让所有城市通电,方式有两种一种直接建供电厂,一种连接有供电厂的城市,使得花费最少
思路:看到数据为2000,应该可以直接算出所有城市之间的连接的花费,很明显地看出是一个最小生成树,可以让所有城市连接一个超级源点,花费为建立供电所的花费,然后跑一遍最小生成树
int f[2005];
struct node{
int x,y;
ll va;
}e[5000005];
vector<int>vt;
vector<pair<int,int>>vt1;
int finds(int x){
return f[x]==x?f[x]:f[x]=finds(f[x]);
}
ll xx[2005],yy[2005],c[2005],d[2005];
bool cmp(node x,node y){
return x.va<y.va;
}
void solve(){
int n,m;
cin>>n;
f[0]=0;
for(int i=1;i<=n;i++){
f[i]=i;
cin>>xx[i]>>yy[i];
}
for(int i=1;i<=n;i++){
cin>>c[i];
}
for(int i=1;i<=n;i++){
cin>>d[i];
}
int cnt=0;
for(int i=1;i<=n;i++){
e[++cnt]={0,i,c[i]};
for(int j=i+1;j<=n;j++){
e[++cnt]={i,j,(abs(xx[i]-xx[j])+abs(yy[i]-yy[j]))*(d[i]+d[j])};
}
}
ll ans=0;
sort(e+1,e+1+cnt,cmp);
for(int i=1;i<=cnt;i++){
if(finds(e[i].x)!=finds(e[i].y)){
ans+=e[i].va;
if(e[i].x==0||e[i].y==0){
vt.push_back(e[i].x+e[i].y);
}else{
vt1.push_back({e[i].x,e[i].y});
}
f[finds(e[i].x)]=finds(e[i].y);
}
}
cout<<ans<<endl;
cout<<vt.size()<<endl;;
for(int i=0;i<vt.size();i++){
cout<<vt[i]<<' ';
}
cout<<endl;
cout<<vt1.size()<<endl;
for(int i=0;i<vt1.size();i++){
cout<<vt1[i].first<<' '<<vt1[i].second<<endl;
}
}