農場ネットワークの最小全域木問題

問題概要

ジョン農場主が町長に選出されました!彼の選挙公約の一つは、町全体にインターネットを導入し、すべての農場を接続することです。もちろん、彼はあなたの助けが必要です。

ジョンはすでに自身の農場に高速ネットワーク回線を設置済みであり、これを他の農場と共有したいと考えています。費用を最小限に抑えるため、すべての農場を接続する最短の光ファイバーを敷設する必要があります。

農場間の接続費用リストが与えられるので、すべての農場を接続し、使用する光ファイバーの総長が最小になる方案を見つける必要があります。

任意の2つの農場間の距離は100000を超えません。

入力

ファイル agrinet.in からデータを読み込みます。
最初の行: 農場の数 N(3 <= N <= 100)。
2行目以降: N×Nの行列が続きます。各農場間の距離を表します。理論上はN行で、各行はN個のスペースで区切られた数字から構成されますが、実際には80文字に制限されているため、一部の行は他の行に続くことがあります。対角線要素は0です(i番目の農場から自身への接続は存在しないため)。

出力

ファイル agrinet.out に出力します。
すべての農場を接続するために必要な光ファイバーの最小長を1行で出力します。

サンプル入力

4

0 4 9 21

4 0 8 17

9 8 0 16

21 17 16 0

サンプル出力

28

実装コード:

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;

struct Edge {
    int weight;
    int source;
    int destination;
};

vector<int> parentSet;
vector<Edge> edgeList;

int findRoot(int node) {
    if (parentSet[node] != node) {
        parentSet[node] = findRoot(parentSet[node]);
    }
    return parentSet[node];
}

void uniteSets(int nodeA, int nodeB) {
    int rootA = findRoot(nodeA);
    int rootB = findRoot(nodeB);
    parentSet[rootB] = rootA;
}

int main() {
    // freopen("agrinet.in", "r", stdin);
    // freopen("agrinet.out", "w", stdout);
    
    int farmCount;
    cin >> farmCount;
    
    parentSet.resize(farmCount + 1);
    for (int i = 1; i <= farmCount; i++) {
        parentSet[i] = i;
    }
    
    for (int i = 1; i <= farmCount; i++) {
        for (int j = 1; j <= farmCount; j++) {
            int distance;
            cin >> distance;
            if (distance != 0 && i < j) {
                edgeList.push_back({distance, i, j});
            }
        }
    }
    
    sort(edgeList.begin(), edgeList.end(), [](const Edge &a, const Edge &b) {
        return a.weight < b.weight;
    });
    
    int totalWeight = 0;
    int edgesUsed = 0;
    
    for (const auto &edge : edgeList) {
        if (findRoot(edge.source) != findRoot(edge.destination)) {
            uniteSets(edge.source, edge.destination);
            totalWeight += edge.weight;
            edgesUsed++;
            
            if (edgesUsed == farmCount - 1) {
                break;
            }
        }
    }
    
    cout << totalWeight << endl;
    return 0;
}

タグ: グラフ理論 最小全域木 クラスカル法 Union-Find C++

6月14日 18:40 投稿