TopCoder 算法比赛图论实战1—最小生成树问题

Problem Statement

这个问题需要求解在一个城市网中,连接所有城市的最小代价,一个典型的最小生成树问题。
需要注意的是,每个城市只能朝一个方向修路,所以两个城市之间的最小代价不是(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
posted on 2006-06-15 16:31  Binary Race  阅读(865)  评论(0编辑  收藏  举报