C#城市最短路径
123
public class City
{
public int Id { get; set; }
public string Name { get; set; }
public List<City> Cities { get; set; } = new List<City>();
public List<Road> Roads { get; set; } = new List<Road>();
}
/// <summary>
/// 城市之间的道路
/// </summary>
public class Road
{
public int Id { get; set; }
public int City1 { get; set; }
public int City2 { get; set; }
public int Days { get; set; }
}
public class CityGraph
{
public List<City> Cities { get; set; } = new List<City>();
public List<Road> Roads { get; set; } = new List<Road>();
public void AddRoad(string c1, string c2, int days = 1)
{
AddRoad(Cities.Find(x => x.Name == c1), Cities.Find(x => x.Name == c2), days);
}
public void AddRoad(City city1, City city2, int days)
{
if(Roads.Exists(x => (x.City1 == city1.Id && x.City2 == city2.Id) || (x.City1 == city2.Id && x.City2 == city1.Id)))
return;
var r = new Road { City1 = city1.Id, City2 = city2.Id, Days = days };
Roads.Add(r);
city1.Roads.Add(r);
city2.Roads.Add(r);
city1.Cities.Add(city2);
city2.Cities.Add(city1);
}
/// <summary>
/// 查找两座城市之间的最短路径
/// </summary>
/// <param name="city1"></param>
/// <param name="city2"></param>
/// <returns></returns>
public List<City> FindShortRoads(City city1, City city2)
{
//以起点城市为根节点,构建城市树
//查找所有到达终点城市的路径
//遍历所有路径,计算路径的深度
//返回最小深度的路径
CityNode root = new CityNode { Id = city1.Id };
Tree(root);
var list = root.FindNode(city2.Id);
if (list.Count == 0)
return null;
// 计算最小深度
int min = list.Min(x => x.Depth());
var node = list.Find(f => f.Depth() == min);
var result = new List<City>();
do
{
result.Insert(0, Cities.Find(x => x.Id == node.Id));
node = node.Parent;
} while (node != null);
return result;
}
/// <summary>
/// 构建城市树
/// </summary>
/// <param name="node"></param>
public void Tree(CityNode node)
{
var city = Cities.Find(x => x.Id == node.Id);
foreach (var item in city.Cities)
{
if (!node.EqualParent(item.Id))
{
var road = Roads.Find(x => (x.City1 == node.Id && x.City2 == item.Id) || (x.City1 == item.Id && x.City2 == node.Id));
node.AddChild(new CityNode { Id = item.Id, Days = road.Days });
}
}
foreach (var item in node.Nodes)
{
Tree(item);
}
}
}
public class CityNode
{
public int Id { get; set; }
public int Days { get; set; }
public CityNode Parent { get; set; }
public List<CityNode> Nodes { get; set; } = new List<CityNode>();
public void AddChild(CityNode node)
{
if (Nodes.Exists(x => x.Id == node.Id))
return;
Nodes.Add(node);
node.Parent = this;
}
public void RemoveChild(CityNode node)
{
if (!Nodes.Exists(x => x.Id == node.Id))
return;
Nodes.Remove(node);
if (node.Parent == this)
node.Parent = null;
}
/// <summary>
/// 判断父节点是否是指定的节点
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public bool EqualParent(int id)
{
if (Parent == null)
return false;
if (Parent.Id == id)
return true;
return Parent.EqualParent(id);
}
/// <summary>
/// 计算深度
/// </summary>
/// <returns></returns>
public int Depth()
{
if (Parent == null)
return Days;
return Parent.Depth() + Days;
}
/// <summary>
/// 查找指定节点
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public List<CityNode> FindNode(int id)
{
if (Id == id)
return new List<CityNode> { this };
List<CityNode> list = new List<CityNode>();
foreach (var item in Nodes)
{
var l = item.FindNode(id);
if (l.Count > 0)
list.AddRange(l);
}
return list;
}
}
示例:
CityGraph cityGraph = new CityGraph();
#region Data
string s = "ABCDEFGHIJKLMNOPQRST";
for (int i = 0; i < s.Length; i++)
cityGraph.Cities.Add(new City { Id = i + 1, Name = s[i].ToString() });
cityGraph.AddRoad("A", "B");
cityGraph.AddRoad("A", "H");
cityGraph.AddRoad("A", "G");
cityGraph.AddRoad("B", "C");
cityGraph.AddRoad("B", "J");
cityGraph.AddRoad("B", "I");
cityGraph.AddRoad("B", "H");
cityGraph.AddRoad("H", "I");
cityGraph.AddRoad("H", "P");
cityGraph.AddRoad("H", "G");
cityGraph.AddRoad("G", "P");
cityGraph.AddRoad("G", "O");
cityGraph.AddRoad("C", "D");
cityGraph.AddRoad("C", "J");
cityGraph.AddRoad("J", "D");
cityGraph.AddRoad("J", "K");
cityGraph.AddRoad("J", "I");
cityGraph.AddRoad("I", "R");
cityGraph.AddRoad("I", "Q");
cityGraph.AddRoad("I", "P");
cityGraph.AddRoad("P", "O");
cityGraph.AddRoad("D", "E");
cityGraph.AddRoad("D", "M");
cityGraph.AddRoad("D", "K");
cityGraph.AddRoad("K", "M");
cityGraph.AddRoad("K", "L");
cityGraph.AddRoad("K", "R");
cityGraph.AddRoad("R", "L");
cityGraph.AddRoad("R", "L");
cityGraph.AddRoad("R", "S");
cityGraph.AddRoad("R", "Q");
cityGraph.AddRoad("E", "F");
cityGraph.AddRoad("E", "M");
cityGraph.AddRoad("M", "F");
cityGraph.AddRoad("M", "N");
cityGraph.AddRoad("M", "L");
cityGraph.AddRoad("L", "N");
cityGraph.AddRoad("L", "T");
cityGraph.AddRoad("L", "S");
cityGraph.AddRoad("S", "T");
cityGraph.AddRoad("N", "T");
#endregion
Random random = new Random();
foreach (var item in cityGraph.Roads)
{
item.Days = random.Next(1, 10);
}
var list = cityGraph.FindShortRoads(cityGraph.Cities[0], cityGraph.Cities.Last());
Debug.WriteLine(list.Select(x => x.Name).Aggregate((x, y) => x + "->" + y));