Gym - 100203H Highways 最小生成树

题意:平面上n个点修路,已经修好了m条,再修若干条使得点之间连通,求最小代价的方案。

思路:基本上是裸的最小生成树了,我这里存边直接存在multyset了,取的时候也比较方便,我本来就是这么考虑的,队友打了一发朴素的排序的超时了。

 

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <fstream>
  4 #include <algorithm>
  5 #include <cmath>
  6 #include <deque>
  7 #include <vector>
  8 #include <queue>
  9 #include <string>
 10 #include <cstring>
 11 #include <map>
 12 #include <stack>
 13 #include <set>
 14 #define LL long long
 15 #define eps 1e-8
 16 #define INF 0x3f3f3f3f
 17 #define MAXN 755
 18 using namespace std;
 19 struct Edge{
 20     int from, to;
 21     LL dis;
 22     Edge(int from, int to, LL dis):from(from), to(to), dis(dis){};
 23     bool operator <(const Edge &b) const{
 24         return dis < b.dis;
 25     }
 26 };
 27 multiset<Edge> s;
 28 struct Point{
 29      int x, y;
 30 }p[MAXN];
 31 LL dis[MAXN][MAXN];
 32 bool vis[MAXN][MAXN];
 33 int father[MAXN];
 34 int scan(){
 35     int res = 0, ch, flag = 0;
 36 
 37     if((ch = getchar()) == '-')
 38         flag = 1;
 39 
 40     else if(ch >= '0' && ch <= '9')
 41         res = ch - '0';
 42     while((ch = getchar()) >= '0' && ch <= '9' )
 43         res = res * 10 + ch - '0';
 44 
 45     return flag ? -res : res;
 46 }
 47 LL getdis(Point a, Point b){
 48     LL x = abs(a.x - b.x);
 49     LL y = abs(a.y - b.y);
 50     return x * x + y * y;
 51 }
 52 int find(int x){
 53     if(father[x] == x) return x;
 54     father[x] = find(father[x]);
 55     return father[x];
 56 }
 57 int main()
 58 {
 59 #ifndef ONLINE_JUDGE
 60     freopen("in.txt", "r", stdin);
 61     //freopen("out.txt", "w", stdout);
 62 #endif // OPEN_FILE
 63     int n = scan();
 64     for(int i = 1; i <= n; i++){
 65         father[i] = i;
 66         p[i].x = scan();
 67         p[i].y = scan();
 68     }
 69     s.clear();
 70     LL dis;
 71     for(int i = 1; i <= n; i++){
 72         for(int j = i + 1; j <= n; j++){
 73             dis = getdis(p[i] ,p[j]);
 74             s.insert(Edge(i, j, dis));
 75         }
 76     }
 77     int m =scan();
 78     int x, y;
 79     for(int i = 1; i <= m; i++){
 80         x = scan();
 81         y = scan();
 82         vis[x][y] = true;
 83         x = find(x);
 84         y = find(y);
 85         if(x == y) continue;
 86         father[x] = y;
 87     }
 88     multiset<Edge>::iterator it = s.begin();
 89     while(it != s.end()){
 90         Edge u = *it;
 91         it++;
 92         if(vis[u.from][u.to] || vis[u.to][u.from]) continue;
 93         x = find(u.from);
 94         y = find(u.to);
 95         if(x == y) continue;
 96         father[x] = y;
 97         printf("%d %d\n", u.from, u.to);
 98     }
 99 
100 }

 

posted on 2015-08-15 23:04  张济  阅读(126)  评论(0编辑  收藏  举报

导航