计蒜客习题:布设光纤


问题描述

蒜国有 n 座基站,现在蒜头君想给基站之间布设光纤,使得任意两座基站都是连通的,光纤传输具有传递性,即如果基站 A 和基站 B 之间有光纤,基站 B 和基站 C 之间有光纤,则基站 A 和基站 C 也是连通的,可以通过中间基站 B 来完成传输。
不同的基站之间布设光纤的费用是不同的,现在蒜头君知道了任意两座基站之间布设光纤的费用,求问如何布设,可以使得任意两座基站都是连通的,且总费用最小。
输入格式
第一行输入一个整数 n(2≤n≤100),表示蒜头基站总数。
接下来输入 n×n 的矩阵。第 i 行第 j 列的整数表示第 i 座基站和第 j 座基站之间布设光纤的费用 wij(0≤wij ≤10,000)。
输出格式
输出一个整数,表示布设光纤的最小总费用,且使任意两座基站都是连通的。
样例输入
4
0 1 5 1
1 0 6 3
5 6 0 2
1 3 2 0
样例输出
4


AC代码

#include 
#include 
#include 
#include 
using namespace std;
int G[110][110];
int INF=0x3f3f3f3f;
int dad[200];

struct edge{
    int u,v,w;
}e[8000];

bool cmp(edge a,edge b)
    {
    return a.wint getdad(int i)
{
    if(dad[i]==i)return dad[i];
    return dad[i]=getdad(dad[i]);
}
int main() {
  int n;
  for (int i = 1; i <= 105; i++)
    dad[i] = i;
  memset(G, INF, sizeof(G));
  cin >> n;
  for (int i = 1; i <= n; i++) {
    for (int j = 1; j <= n; j++) {
      int a;
      cin >> a;
      if (a != 0)
        G[i][j] = a;
    }
  }
  int eid = 1;
  for (int i = 1; i <= n; i++) {
    for (int j = i + 1; j <= n; j++) {
      if (G[i][j] < INF) {
        e[eid].u = i;
        e[eid].v = j;
        e[eid].w = G[i][j];
        eid++;
      }
    }
  }
  sort(e+1, e+eid, cmp);
  int rest = n;
  int ans = 0;
  for (int i = 1; i < eid - 1 && rest > 1; i++) {
    int x = e[i].u;
    int y = e[i].v;
    if (getdad(x) != getdad(y)) {
      dad[getdad(x)] = getdad(y);
      ans += e[i].w;
      rest--;
    }
  }
  cout << ans;
  return 0;
}

你可能感兴趣的:(#,图论,算法竞赛刷题,计蒜客NOIP习题)