1. 程式人生 > >C - 暢通工程 (HDU - 1863)

C - 暢通工程 (HDU - 1863)

暢通工程 通過 n) 題目 評估 生成樹 class break namespace

- 題目大意

省政府“暢通工程”的目標是使全省任何兩個村莊間都可以實現公路交通(但不一定有直接的公路相連,只要能間接通過公路可達即可)。經過調查評估,得到的統計表中列出了有可能建設公路的若幹條道路的成本。因此求出最少的成本為多少?

- 解題思路

最小生成樹的問題,用kruskal算法,kruskal算法是一種貪心策略,每次放長度(本題可以看做是建路的成本)最小的邊,如果兩個點屬於同一個集合就不放,否則會構成環,每放一個點我們記錄一次,最後把所有點都連通了就結束算法。

- 代碼

#include<iostream>
#include<algorithm>
using namespace std;
const int MAX = 1e5 + 50;
int fa[MAX];

struct Edge {
	int u, v, w;
	bool operator<(const Edge &rhs)const {
		return w < rhs.w;
	}
}e[MAX];
void init(int n)
{
	for (int i = 1; i <= n; i++)
		fa[i] = i;
}

int find(int x)
{
	if (x == fa[x])
		return x;
	else
	{
		return fa[x] = find(fa[x]);
	}
}

bool Union(int x, int y)
{
	int fx = find(x), fy = find(y);
	if (fx == fy)
		return false;
	else
	{
		fa[fx] = fy;
		return true;
	}
}

int kruskal(int n, int m)
{
	sort(e, e + m);
	init(n);
	int sum = 0;
	for (int i = 1; i <= m; i++)
	{
		int u = e[i].u, v = e[i].v, w = e[i].w;
		if (Union(u, v))
		{
			sum += w;
		}
	}
	return sum;
}
int main()
{
	int n,m,tmp,sum;
	while (cin >> n >> m)
	{
		if (n == 0)
			break;
		for (int i = 1; i <= n; i++)
			cin >> e[i].u >> e[i].v >> e[i].w;
		tmp = kruskal(m, n);
		sum = 0;
		for (int i = 1; i <= m; i++)
		{
			if (fa[i] == i)
				sum++;
		}
		if (sum > 1)
			cout << "?" << endl;
		else
		{
			cout << tmp << endl;
		}
	}
	return 0;
}

  

C - 暢通工程 (HDU - 1863)