题意::求让所有城市连接起来的最小花费 连接方式(1:在城市建立发电站 2:用电线连接有发电站的城市 )
思路::最小生成树,倘若在城市建电站,花费 c[ i ] ,反之连接 其他城市 花费 k[i]+k[j])*(i,j曼哈顿距离)
我们可以建立一个虚点,他到所有城市的花费即为自建花费
然后跑最小生成树,不仅保证图联通,还是最小花费,需要注意一下自建电站情况
Kruskal

1 #include<bits/stdc++.h>
2 #define ll long long
3 const ll inf=1e15+7;
4 using namespace std;
5 const int maxn=2005;
6
7 struct node
8 {
9 int x,y;
10 ll x1,y1,val;
11 bool operator < (const node &lh)const {return val<lh.val;}
12 }ma[maxn],mb[maxn*maxn+2500];
13 int n,t=0,f[maxn],a[maxn];
14 ll sum=0,c[maxn],k[maxn];
15 vector<pair<int,int> >v;
16
17 ll dis(int x,int y)
18 {
19 ll num=(abs(ma[x].x1-ma[y].x1)+abs(ma[x].y1-ma[y].y1))*(k[x]+k[y]);
20 return num;
21 }
22 int getfind(int x)
23 {
24 return x==f[x]?x:f[x]=getfind(f[x]);
25 }
26 void init()
27 {
28 for(int i=0;i<=n;i++)f[i]=i;
29 }
30 int main()
31 {
32 v.clear();
33 scanf("%d",&n);
34 for(int i=1;i<=n;i++){
35 scanf("%lld%lld",&ma[i].x1,&ma[i].y1);
36 }
37 for(int i=1;i<=n;i++){
38 scanf("%lld",&c[i]);
39 }
40 for(int i=1;i<=n;i++){
41 scanf("%lld",&k[i]);
42 }
43 int ant=0;
44 for(int i=1;i<=n;i++){
45 for(int j=i+1;j<=n;j++){
46 mb[++ant].x=i;mb[ant].y=j;mb[ant].val=dis(i,j);
47 }
48 }
49 n++;init();
50 for(int i=1;i<n;i++){
51 mb[++ant].x=i;mb[ant].y=n;mb[ant].val=c[i];
52 }
53 sort(mb+1,mb+ant+1);
54 for(int i=1;i<=ant;i++){
55 int k1=mb[i].x,k2=mb[i].y;
56 int t1=getfind(k1),t2=getfind(k2);
57 if(t1!=t2){
58 f[t1]=t2;
59 sum+=mb[i].val;
60 if(k2==n){a[++t]=k1;}
61 else{
62 v.push_back(make_pair(k2,k1));
63 }
64 }
65 }
66 printf("%lld\n%d\n",sum,t);
67 for(int i=1;i<=t;i++){
68 printf("%d ",a[i]);
69 }
70 printf("\n%d\n",v.size());
71 for(int i=0;i<v.size();i++){
72 printf("%d %d\n",v[i].first,v[i].second);
73 }
74 return 0;
75 }
Prime

1 #include<bits/stdc++.h>
2 #define ll long long
3 const ll inf=1e15+7;
4 using namespace std;
5 const int maxn=2005;
6
7 struct node
8 {
9 ll x,y;
10 }ma[maxn],mb[maxn];
11 int n,t=0;
12 ll sum=0;
13 ll c[maxn],a[maxn];
14 ll k[maxn],lowdis[maxn];
15 ll mst[maxn];
16
17 vector<pair<ll,ll> >v;
18
19 ll dis(int x,int y)
20 {
21 ll num=(abs(ma[x].x-ma[y].x)+abs(ma[x].y-ma[y].y))*(k[x]+k[y]);
22 return num;
23 }
24
25 void prime()
26 {
27 for(int i=1;i<=n;i++){
28 lowdis[i]=c[i];
29 }
30 for(int i=1;i<=n;i++)
31 {
32 ll minn=inf;
33 ll mind=0;
34 for(int j=1;j<=n;j++)
35 {
36 if(minn>lowdis[j]&&lowdis[j]!=0){
37 minn=lowdis[j];
38 mind=j;
39 }
40 }
41 lowdis[mind]=0;
42 sum+=minn;
43 if(!mst[mind]){
44 a[++t]=mind;
45
46 }
47 else{
48 v.push_back(make_pair(mst[mind],mind));
49 }
50 for(int j=1;j<=n;j++){
51 if(lowdis[j]>dis(mind,j)){
52 lowdis[j]=dis(mind,j);mst[j]=mind;
53 }
54 }
55 }
56 printf("%lld\n%d\n",sum,t);
57 }
58 int main()
59 {
60 scanf("%d",&n);
61 for(int i=1;i<=n;i++){
62 scanf("%lld%lld",&ma[i].x,&ma[i].y);
63 }
64 for(int i=1;i<=n;i++){
65 scanf("%lld",&c[i]);
66 }
67 for(int i=1;i<=n;i++){
68 scanf("%lld",&k[i]);
69 }
70 prime();
71 for(int i=1;i<=t;i++){
72 printf("%lld ",a[i]);
73 }
74 printf("\n%d\n",v.size());
75 for(int i=0;i<v.size();i++){
76 printf("%lld %lld\n",v[i].first,v[i].second);
77 }
78 return 0;
79 }
码风有点怪,还能看
