当前位置:   article > 正文

codeforces 1245D(最小生成树)_codeforces - 1245d

codeforces - 1245d

题面链接:https://codeforces.com/problemset/problem/1245/D

题意大概是给你一些城市的坐标,可以在城市中建立发电站,也可以让某个城市和已经建好发电站的城市连接,保证在这两种操作下使得所有的城市供电,在城市建发电站需要花费Ci,城市a和城市b连接需要花费(|Xa-Xb| + |Ya-Yb| )*(Ka+Kb),求最小的花费让所有城市通电。

思路:首先建立一个源点,连接各个城市,边权就是建发电站费用Ci,若选择此边则表示是在该城市建了发电站。

           剩下的城市互相按照题意要求建边,建完全图。

           最终模型就抽象成求最小生成树,用克鲁斯卡尔算法跑一下即可

AC代码:

  1. #include<iostream>
  2. #include<vector>
  3. #include<set>
  4. #include<cstdio>
  5. #include<algorithm>
  6. #define maxn 2005
  7. using namespace std;
  8. typedef long long ll;
  9. struct node{
  10. int from,to;
  11. ll cost;
  12. }e[maxn*maxn];//存储边的信息
  13. int father[maxn];
  14. int cnt,N,city;
  15. vector<int> sta;//存建发电站的城市
  16. vector<int> citya,cityb;//存储a b城市表示ab之间有电线
  17. bool cmp(node a,node b){//比较函数
  18. return a.cost < b.cost ;
  19. }
  20. void init(){//初始化
  21. cnt = 0;
  22. for(int i = 0;i<=N;i++){
  23. father[i] = i;
  24. }
  25. }
  26. int find(int x){//寻找根
  27. if(x == father[x]) return x;
  28. return father[x] = find(father[x]);
  29. }
  30. bool same(int x,int y){//判断是否在一个集合
  31. return find(x)==find(y);
  32. }
  33. void unionSet(int x,int y){ //并查集合并
  34. int u = find(x),v = find(y);
  35. if(u==v) return ;
  36. father[u] = v;
  37. }
  38. long long kruskal(){ //求最小生成树
  39. ll res = 0;
  40. std::sort(e,e+cnt,cmp);
  41. for(int i = 0;i<cnt;i++){
  42. if(same(e[i].from,e[i].to )) continue;
  43. unionSet(e[i].from ,e[i].to );
  44. if(e[i].from == 0 || e[i].to == 0){//判一下是否在城市建了发电站(利用源点判断)
  45. if(e[i].from == 0) sta.push_back(e[i].to );
  46. else sta.push_back(e[i].from);
  47. }
  48. else{//如果不是,存一些a,b两座连接的城市
  49. citya.push_back(e[i].from ),cityb.push_back(e[i].to);
  50. }
  51. res+=e[i].cost ;
  52. }
  53. return res;
  54. }
  55. void addedge(int u,int v,ll C){ //建边操作
  56. e[cnt].from = u,e[cnt].to = v,e[cnt].cost = C;
  57. cnt++;
  58. }
  59. int main(){
  60. cin>>N;
  61. init();
  62. vector<long long> vx,vy;
  63. vector<long long> c,k;
  64. for(int i = 0;i<N;i++){
  65. int x,y;cin>>x>>y;
  66. vx.push_back(x),vy.push_back(y);
  67. }
  68. for(int i = 0;i<N;i++){
  69. ll tc;cin>>tc;
  70. c.push_back(tc);
  71. }
  72. for(int i = 0;i<N;i++){
  73. ll tk;cin>>tk;
  74. k.push_back(tk);
  75. }
  76. for(int i = 0;i<N;i++){//建立源点,和各个城市连接
  77. addedge(0,i+1,c[i]);
  78. }
  79. for(int i = 0;i<N;i++){//城市和城市之间建完全图
  80. for(int j = i+1;j<N;j++){
  81. ll c = (abs(vx[i]-vx[j])+abs(vy[i]-vy[j]))*(k[i]+k[j]);
  82. addedge(i+1,j+1,c);
  83. }
  84. }
  85. ll ans = kruskal();
  86. cout<<ans<<endl;
  87. cout<<sta.size()<<endl;
  88. for(int i = 0;i<sta.size();i++){
  89. if(i==0) cout<<sta[i];
  90. else cout<<" "<<sta[i];
  91. }
  92. cout<<endl;
  93. cout<<citya.size()<<endl;
  94. for(int i = 0;i<citya.size() ;i++){
  95. cout<<citya[i]<<" "<<cityb[i]<<endl;
  96. }
  97. return 0;
  98. }

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/article/detail/52937
推荐阅读
相关标签
  

闽ICP备14008679号