Constructing Roads ——最小生成树

May 26, 2013
Graph

题目链接:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=24534#problem/B 题目大意:   给邻接矩阵,和已经建立好的几条边。求最小生成树权值。 题目思路:   方法就是把已将建立好的边的权值赋值为0即可。


#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
#define MAXN 110
#define MAXM 5009
typedef struct edge {
  int u, v, w;
  bool operator < (const edge &other) const {
    return w < other.w;
  }
}edge;
edge edges[MAXM];
int parent[MAXN];
int n, m, i, j;
void init() {
  for (i = 1; i <= n; ++i) parent[i] = -1;
}
int find(int x) {
  int s;
  for (s = x; parent[s] >= 0; s = parent[s]) ;
  while (s != x) {
    int tmp = parent[x];
    parent[x] = s;
    x = tmp;
  }
  return s;
}
void Union(int R1, int R2) {
  int r1 = find(R1), r2 = find(R2), tmp = parent[r1] + parent[r2];
  if (parent[r1] > parent[r2]) {
    parent[r1] = r2; parent[r2] = tmp;
  } else {
    parent[r2] = r1; parent[r1] = tmp;
  }
}
void kruscal() {
  int sum = 0, num = 0, u, v;
  init();
  for (i = 0; i < m; ++i) {
    u = edges[i].u; v = edges[i].v;
    if (find(u) != find(v)) {
      sum += edges[i].w; num++;
      Union(u, v);
    }
    if (num >= n-1) break;
  }
  printf("%d\n", sum);
}
int ma[MAXN][MAXN];
int main(void) {
#ifndef ONLINE_JUDGE
  freopen("hust_b.in", "r", stdin);
#endif
  while (~scanf("%d", &n)) {
    for (i = 1; i <= n; ++i) {
      for (j = 1; j <= n; ++j) {
        scanf("%d", &ma[i][j]);
      }
    }
    m = 0;
    int q, u, v; scanf("%d", &q);
    while (q--) {
      scanf("%d%d", &u, &v);
      ma[u][v] = ma[v][u] = 0;
    }
    for (i = 1; i <= n; ++i) {
      for (j = 1; j < i; ++j) {
        edges[m].u = i; edges[m].v = j; edges[m].w = ma[i][j];
        m++;
      }
    }
    sort(edges, edges+m);
    kruscal();
  }

  return 0;
}

这题以前做过……模板题

comments powered by Disqus