8.14-T1村通网(pupil)
题目大意
要建设一个村庄的网络
有两种操作可选
1、给中国移动交宽带费,直接连网,花费为 A。
2、向另外一座有网的建筑,安装共享网线,花费为 B×两者曼哈顿距离。
题解
显然的最小生成树的题
见一个虚拟源点,将每个点和那个虚拟源点连一个边权为A的边
其余每个点之间连边,边权即为曼哈顿距离*B
于是自信的以为曼哈顿距离就是两点之间的距离的我,怎么都过不了大样例,于是快乐gg,快乐崩溃...
#include<bits/stdc++.h> #define ll long long #define db double using namespace std; inline int read() { int sum = 0,p = 1; char ch = getchar(); while(ch < '0' || ch > '9') { if(ch == '-') p = -1; ch = getchar(); } while(ch >= '0' && ch <= '9') { (sum *= 10) += ch - '0'; ch = getchar(); } return sum * p; } const int N = 1e3 + 5; int n,A,B; struct node { int x,y; } pot[N]; int cnt,fa[N],tot; struct edge { int frm,to; ll wei; } e[N * N /2 + N]; ll ans; void add(int a,int b,ll c) { e[++cnt].frm = a; e[cnt].to = b; e[cnt].wei = c; } bool cmp(edge a,edge b) { return a.wei < b.wei; } int findfa(int x) { if(fa[x] == x) return x; else return fa[x] = findfa(fa[x]); } void kruskal() { sort(e+1,e+cnt+1,cmp); for(int i = 0;i <= n;i++) fa[i] = i; for(int i = 1;i <= cnt;i++) { int u = findfa(e[i].frm); int v = findfa(e[i].to); if(u == v) continue; fa[v] = u; tot++; ans += e[i].wei; if(tot == n) return; } } int main() { freopen("pupil.in","r",stdin); freopen("pupil.out","w",stdout); n = read(),A = read(),B = read(); for(int i = 1; i <= n; i++) { pot[i].x = read(); pot[i].y = read(); } for(int i = 1; i <= n; i++) for(int j = i + 1; j <= n; j++) { ll xx= abs(pot[i].x - pot[j].x); ll yy= abs(pot[i].y - pot[j].y);; add(i,j,(xx + yy) * B); // add(j,i,len * B); } for(int i = 1;i <= n;i++) { add(0,i,A); // add(i,0,A); } kruskal(); printf("%lld\n",ans); return 0; } //不知道曼哈顿距离可还行