TopCoder 算法比赛图论实战1—最小生成树问题
这个问题需要求解在一个城市网中,连接所有城市的最小代价,一个典型的最小生成树问题。
需要注意的是,每个城市只能朝一个方向修路,所以两个城市之间的最小代价不是(X+Y)/2,而是Max(X,)
解决方案如下:
using System;
using System.Collections.Generic;
using System.Collections;
using System.Text;
//最小生成树问题
public class CityLink
{
int N;
bool[,]
map;
bool[]
visited;
bool AllConnect()
{
visited = new bool[N];//very
importent!!!!
dfs(0);
for (int i = 0;
i < N; i++)
if (!visited[i])
return false;
return true;
}
void dfs(int i)
{
visited[i] = true;
for (int j = 0;
j < N; j++)
if (map[i, j] && !visited[j])
dfs(j);
}
public int timeTaken(int[]
x, int[]
y)
{
N = x.Length;
int[,] d = new int[N,
N];
map = new bool[N,
N];
List<int>
edgesv = new List<int>();//所有不同长度的边
Hashtable edges = new Hashtable();//每个边都连接了哪些顶点
for (int i = 0;
i != N;
i++)
for (int j = i;
j != N;
j++)
{
if (x[i] == x[j])
d[i, j] = (Math.Abs(y[i] - y[j]) + 1) / 2;
else if (y[i]
== y[j])
d[i, j] = (Math.Abs(x[i] - x[j]) + 1) / 2;
//只能朝一个方向走,不能改变方向?
else
d[i, j] = Math.Max(Math.Abs(x[i] - x[j]),
Math.Abs(y[i] - y[j]));
//d[i, j] = (Math.Abs(x[i] - x[j]) + Math.Abs(y[i] - y[j]) + 1) / 2;
if (!edgesv.Contains(d[i, j]))
edgesv.Add(d[i, j]);
if (edges.Contains(d[i, j]))
{
((List<int>)edges[d[i,
j]]).Add(i);
((List<int>)edges[d[i,
j]]).Add(j);
}
else
{
List<int>
tmp = new List<int>();
tmp.Add(i);
tmp.Add(j);
edges.Add(d[i, j], tmp);
}
}
edgesv.Sort();//Kruskal算法需要从最小的边开始,所以这里排序一下
//Kruskal
for (int i = 0;
i < edgesv.Count; i++)
{
//Conect two points
List<int>
points = (List<int>)edges[edgesv[i]];
for (int j = 0;
j < points.Count; j += 2)
{
map[points[j], points[j + 1]] = true;
map[points[j+1], points[j]] = true;
}
if (AllConnect())
return edgesv[i];
}
return -1;
}
Ecogiser's Blog