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

本文深入探讨了最小生成树问题,特别是在城市网中寻找连接所有城市的最小代价路径。通过使用Kruskal算法,文章详细解释了如何处理城市间单向修路的限制,并提供了具体的实现代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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;
}

> aggbug.ashx?id=77febd91-a9d2-4a95-9d54-8802a1736ec7

Ecogiser's Blog

转载于:https://www.cnblogs.com/ecogiser/archive/2006/06/15/477617.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值