给定 (n) 个点 ((nleq2000)),在第 (i) 个点上建立一个基站需要 (c_i) 的代价,连接两个点需要 ((|x_i-x_j|+|y_i-y_j|)(k_i+k_j)) 的代价。对于一个点要么建立基站,要么连接建立基站的点。问最小代价是多少,同时输出建立基站的点和线路。
Solution
这个万年老题到底被出过多少遍了啊
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 2005;
struct edge {
int u,v,w,fg;
bool operator < (const edge &b) const {
return w < b.w;
}
} e[N*N];
int n,t1,t2,t3,c[N],k[N],x[N],y[N],ind,ans,cnt1,cnt2,fa[N];
int find(int p) {
return fa[p]==p?p:fa[p]=find(fa[p]);
}
void merge(int p,int q) {
p=find(p); q=find(q);
if(p-q) fa[p]=q;
}
signed main() {
ios::sync_with_stdio(false);
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++) {
for(int j=1;j<i;j++) {
e[++ind]={i,j,(k[i]+k[j])*(abs(x[i]-x[j])+abs(y[i]-y[j])),0};
}
}
for(int i=1;i<=n;i++) {
e[++ind]={0,i,c[i],0};
}
for(int i=1;i<=n;i++) fa[i]=i;
sort(e+1,e+ind+1);
for(int i=1;i<=ind;i++) {
edge &ed=e[i];
if(find(ed.u)!=find(ed.v)) {
ans+=ed.w;
ed.fg=1;
merge(ed.u,ed.v);
}
}
for(int i=1;i<=ind;i++) {
edge &ed=e[i];
if(ed.fg) {
if(ed.u==0) {
++cnt1;
}
if(ed.v==0) {
++cnt1;
}
if(ed.u && ed.v) {
++cnt2;
}
}
}
cout<<ans<<endl;
cout<<cnt1<<endl;
for(int i=1;i<=ind;i++) {
edge &ed=e[i];
if(ed.fg) {
if(ed.u==0) {
cout<<ed.v<<" ";
}
if(ed.v==0) {
cout<<ed.u<<" ";
}
}
}
cout<<endl;
cout<<cnt2<<endl;
for(int i=1;i<=ind;i++) {
edge &ed=e[i];
if(ed.fg) {
if(ed.u && ed.v) {
cout<<ed.u<<" "<<ed.v<<endl;
}
}
}
}