nの町の間にはいくつかの道路接続がありますが、道路はすべて荒廃した地球の道路です。政府は現在、一部の地球道路を標準道路に変換する準備を進めており、標準道路がすべての町と都市を最小の総コストで接続できることを望んでいます。ただし、町の1つは特別であり、地形によって制限されています。2つの標準道路のみが可能です。町を通過します。上記の条件を満たす、総コストが最小の変革計画を見つけるためのプログラムを作成してください。変革計画がない場合は、それも特定できます。道路が双方向であると仮定します。
入力形式:
入力には複数のデータセットが含まれています。データの各グループの最初の行は、3つの整数n、v、およびeであり、すべて50を超えません。nは町の数であり、町には0からn-1までの番号が付けられます。vは、標準道路が2つ多い町の数、eは既存の未舗装道路の数、e行は各道路の情報を表し、各行には3つの非負の整数a、b、cがあります。 、町aを表し、町bの間に既存の道路があります。標準道路に変換すると、コストはcになります。
出力形式:
データのグループごとに1行を出力します。これは整数であり、要件を満たすための最小コストを示します。変更計画がない場合は、-1を出力します。
入力サンプル:
5 0 8
0 1 1
0 2 1
0 3 1
0 4 1
1 4100
1 2100
2 3100
3 4100
5 0 4
0 1 1
0 2 1
0 3 1
0 4 1
サンプル出力:
202
-1
クラスカルアルゴリズムが使用されます。欲張り戦略では、最小の重みを持つエッジを選択するときに、リングを形成できないことを考慮する必要があります。同時に、問題の特別な要件を満たす必要があります。
当時、私はそれが最小スパニングツリーの問題だと思っていました。バックグラウンドのテストデータもまさにこれです(テストポイントは2つしかないので、実際には少し少ないです)、トレーニングキャンプの大物、そしてそれはたまたま私たちのクラスです。テストデータによると、このグループのテストは質問の意味に従って4を出力するはずですが、実際の出力は-1であり、要件を満たす最小全域木がそうではないことを示しています。必然的に最後のもの。
4 0 4
0 1 1
0 2 1
0 3 1
1 2 2
バックグラウンドでデータコードをテストできます。
#include <algorithm>
#include <iostream>
using namespace std;
typedef struct {
int u;
int v;
int w;
} Road;
Road road[51];
int f[51];
bool cmp(Road r1, Road r2) {
return r1.w < r2.w; }
void init() {
for (int i = 0; i < 51; i++) {
f[i] = i;
}
}
int find(int x) {
if (x == f[x])
return x;
return f[x] = find(f[x]);
}
int merge(int x, int y) {
int a = find(x);
int b = find(y);
if (a != b) {
f[b] = a;
return 1;
}
return 0;
}
int main() {
int n, v, e;
while (scanf("%d %d %d", &n, &v, &e) != EOF) {
init();
for (int i = 0; i < e; i++) {
scanf("%d %d %d", &road[i].u, &road[i].v, &road[i].w);
}
int cnt = 0, sum = 0, num = 0;
sort(road, road + e, cmp);
for (int i = 0; i < e; i++) {
if ((road[i].u == v || road[i].v == v) && cnt < 2) {
if (merge(road[i].u, road[i].v)) {
sum += road[i].w;
cnt++;
num++;
}
} else if (road[i].u != v && road[i].v != v) {
if (merge(road[i].u, road[i].v)) {
sum += road[i].w;
num++;
}
}
if (num == n - 1)
break;
}
if (num == n - 1 && cnt <= 2)
printf("%d\n", sum);
else
printf("-1\n");
}
return 0;
}