poj 2421

作者: failed | 来源:发表于2018-03-01 01:31 被阅读0次

裸kruskal,算法大致是:
对每条边排序,从小到大。如果每次选取的边起点和终点在一个连通分量里,这条边将不会被加入,否则成环。
把题目中已经建立好路径的边用flag数组标记,并把边权改为0。

#include <algorithm>
#include <cstdio>
#include <cstring>
#include <iostream>
#define MAX 110
#define INF 0x3f3f3f3f

using namespace std;

int n, q;
int map[MAX][MAX];
int Fa[MAX];
int flag[MAX][MAX];
int t;
struct Edge {
int s, e, len;
} edge[MAX * MAX];

bool cmp(const Edge &a, const Edge &b) { return a.len < b.len; }
int find(int x) {
if (x != Fa[x])
  return find(Fa[x]);
else
  return x;
}
bool Union(int x, int y) {
int fax = find(x);
int fay = find(y);
if (fax == fay)
  return false;

else {
  Fa[fax] = fay;
  return true;
}
}
int kruskal() {
int sum = 0;
sort(edge, edge + t, cmp);
for (int i = 0; i < n; i++)
  Fa[i] = i;

for (int i = 0; i < t; i++) {
  if (Union(edge[i].s, edge[i].e))
    sum += edge[i].len;
}

return sum;
}

int main() {
while (~scanf("%d", &n)) {
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < n; j++) {
      scanf("%d", &map[i][j]);
    }
  }
  scanf("%d", &q);
  int s, e;
  memset(flag, 0, sizeof(flag));
  for (int i = 0; i < q; i++) {
    scanf("%d%d", &s, &e);
    flag[s - 1][e - 1] = 1;
  }
  t = 0;
  for (int i = 0; i < n - 1; i++) {
    for (int j = i + 1; j < n; j++) {
      if (flag[i][j]) {
        edge[t].s = i;
        edge[t].e = j;
        edge[t++].len = 0;
      } else

      {
        edge[t].s = i;
        edge[t].e = j;
        edge[t++].len = map[i][j];
      }
    }
  }
  printf("%d\n", kruskal());
}

return 0;
}

相关文章

网友评论

    本文标题:poj 2421

    本文链接:https://www.haomeiwen.com/subject/vfmwxftx.html