codeforces Codeforces Round #597 (Div. 2) D. Shichikuji and Power Grid
#include<bits/stdc++.h> using namespace std ; int n; struct City { int id; long long x,y; //坐标 long long cc,kk; //自建的花费,连线的花费 bool self;//是否建站 int fa;//连线的站 bool operator < (const City & a)const { return cc<a.cc; } } c[2005]; int main() { scanf("%d",&n); for(int i=1; i<=n; i++) { c[i].id=i;//发电站编号 c[i].self=1; //首先都默认是自建的 scanf("%lld%lld",&c[i].x,&c[i].y); //输入坐标 } for(int i=1; i<=n; i++) scanf("%lld",&c[i].cc); //初始都为自建 for(int i=1; i<=n; i++) scanf("%lld",&c[i].kk);//连线 long long ans=0,selfnum=0; for(int i=1; i<=n; i++) { sort(c+i,c+1+n);//大概就是要随时排序,每次找到最小的,每次排序要排除前一次的,防止多加费用 ans+=c[i].cc; //费用 if(c[i].self) selfnum++; //判断是否自建 for(int j=i+1; j<=n; j++) { long long cost=(c[i].kk+c[j].kk)*(abs(c[i].x-c[j].x)+abs(c[i].y-c[j].y)); if(cost<c[j].cc) { c[j].cc=cost; c[j].self=0;//放弃自建,说要已经和别的站建立了联系 c[j].fa=c[i].id; } } } printf("%lld\n%lld\n",ans,selfnum); for(int i=1; i<=n; i++) if(c[i].self) printf("%d ",c[i].id); printf("\n%lld\n",n-selfnum); for(int i=1; i<=n; i++) if(!c[i].self) printf("%d %d\n",c[i].id,c[i].fa); return 0; } /*首先假设每个点都自建,那么每个点的代价就是自建代价。 然后按照代价排序,用代价最小的点去更新后面那些点, 如果能更新用电代价,就把那些点连接到当前点。 然后进入下一轮循环,排除上一次代价最小的点,把剩下的点再次按照代价排序, 然后用这些点中代价最小的去更新其他的,以此类推。 */