Advertisement
sylviapsh

Graphs (from Friends in need)

Jun 24th, 2013
48
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 14.83 KB | None | 0 0
  1. namespace Graphs
  2. {
  3.     using System;
  4.     using System.Collections;
  5.     using System.Collections.Generic;
  6.     using System.Linq;
  7.     using System.Text;
  8.  
  9.     public class Program
  10.     {
  11.         private static readonly HashSet<int> hospitals = new HashSet<int>();
  12.         private static readonly Graph<int> graph = new Graph<int>();
  13.  
  14.         /// <summary>
  15.         /// Friends in Need
  16.         /// On the first line will be read three integer numbers N, M and H (separated by a single white space), that represent corresponding the number of points on the map (both hospitals and homes), the number of streets between points and the number of hospitals.
  17.         /// On the second line will be H integer numbers, the points on the map that are hospitals. All the rest of the points are homes.
  18.         /// On the next M lines will be the streets. Each line contains three positive integer numbers F, S and D. That means that there is a street between points F and S, and the distance between them is D. All the streets are directional, i.e. if a street from A to B exists, there is a street from B to A.
  19.         /// 3 2 1
  20.         /// 1
  21.         /// 1 2 1
  22.         /// 3 2 2
  23.         /// Output: 4
  24.         /// </summary>
  25.         /// <param name="args"></param>
  26.         static void Main(string[] args)
  27.         {
  28.             string[] buffer = Console.ReadLine().Split(' ');
  29.             int n = int.Parse(buffer[0]);
  30.             int m = int.Parse(buffer[1]);
  31.             int h = int.Parse(buffer[2]);
  32.             buffer = Console.ReadLine().Split(' ');
  33.             int nodeName;
  34.             for (int i = 0; i < h; i++)
  35.             {
  36.                 nodeName = int.Parse(buffer[i]);
  37.                 hospitals.Add(nodeName);
  38.                 graph.AddNode(nodeName);
  39.             }
  40.  
  41.             for (int i = 0; i < m; i++)
  42.             {
  43.                 buffer = Console.ReadLine().Split(' ');
  44.                 graph.AddConnection(int.Parse(buffer[0]), int.Parse(buffer[1]), int.Parse(buffer[2]), true);
  45.             }
  46.  
  47.             int sumDistance = int.MaxValue;
  48.             foreach (var hospital in hospitals)
  49.             {
  50.                 List<Node<int>> nodes = graph.FindShortestDistanceToAllNodes(hospital);
  51.                 int currentDistance = 0;
  52.                 foreach (var node in nodes)
  53.                 {
  54.                     if (!hospitals.Contains(node.Name))
  55.                     {
  56.                         currentDistance += (int)node.DijkstraDistance;
  57.                     }
  58.                 }
  59.  
  60.                 if (currentDistance < sumDistance)
  61.                 {
  62.                     sumDistance = currentDistance;
  63.                 }
  64.             }
  65.  
  66.             Console.WriteLine(sumDistance);
  67.         }
  68.     }
  69.  
  70.     public class Graph<T>
  71.     {
  72.         internal IDictionary<T, Node<T>> Nodes { get; private set; }
  73.  
  74.         private readonly HashSet<Node<T>> visited;
  75.  
  76.         public Graph()
  77.         {
  78.             Nodes = new Dictionary<T, Node<T>>();
  79.             visited = new HashSet<Node<T>>();
  80.         }
  81.  
  82.         public void AddNode(T name)
  83.         {
  84.             var node = new Node<T>(name);
  85.             if (Nodes.ContainsKey(name))
  86.             {
  87.                 throw new ArgumentException(string.Format("Node with name {0} is existing in the graph.", name));
  88.             }
  89.             Nodes.Add(name, node);
  90.         }
  91.  
  92.         public void AddConnection(T fromNode, T toNode, int distance, bool twoWay)
  93.         {
  94.             if (!Nodes.ContainsKey(fromNode))
  95.             {
  96.                 this.AddNode(fromNode);
  97.             }
  98.  
  99.             if (!Nodes.ContainsKey(toNode))
  100.             {
  101.                 this.AddNode(toNode);
  102.             }
  103.  
  104.             Nodes[fromNode].AddConnection(Nodes[toNode], distance, twoWay);
  105.         }
  106.  
  107.         public List<Node<T>> FindShortestDistanceToAllNodes(T startNodeName)
  108.         {
  109.             if (!Nodes.ContainsKey(startNodeName))
  110.             {
  111.                 throw new ArgumentOutOfRangeException(string.Format("{0} is not containing in the graph.", startNodeName));
  112.             }
  113.  
  114.             SetShortestDistances(Nodes[startNodeName]);
  115.             List<Node<T>> nodes = new List<Node<T>>();
  116.             foreach (var item in Nodes)
  117.             {
  118.                 if (!item.Key.Equals(startNodeName))
  119.                 {
  120.                     nodes.Add(item.Value);
  121.                 }
  122.             }
  123.             return nodes;
  124.         }
  125.  
  126.         private void SetShortestDistances(Node<T> startNode)
  127.         {
  128.             PriorityQueue<Node<T>> queue = new PriorityQueue<Node<T>>();
  129.  
  130.             // set to all nodes DijkstraDistance to PositiveInfinity
  131.             foreach (var node in Nodes)
  132.             {
  133.                 if (!startNode.Name.Equals(node.Key))
  134.                 {
  135.                     node.Value.DijkstraDistance = double.PositiveInfinity;
  136.                     //queue.Enqueue(node.Value);
  137.                 }
  138.             }
  139.  
  140.             startNode.DijkstraDistance = 0.0d;
  141.             queue.Enqueue(startNode);
  142.  
  143.             while (queue.Count != 0)
  144.             {
  145.                 Node<T> currentNode = queue.Dequeue();
  146.  
  147.                 if (currentNode.DijkstraDistance == double.PositiveInfinity)
  148.                 {
  149.                     break;
  150.                 }
  151.  
  152.                 foreach (var neighbour in Nodes[currentNode.Name].Connections)
  153.                 {
  154.                     double subDistance = currentNode.DijkstraDistance + neighbour.Distance;
  155.  
  156.                     if (subDistance < neighbour.To.DijkstraDistance)
  157.                     {
  158.                         neighbour.To.DijkstraDistance = subDistance;
  159.                         queue.Enqueue(neighbour.To);
  160.                     }
  161.                 }
  162.             }
  163.         }
  164.  
  165.         public void SetAllDijkstraDistanceValue(double value)
  166.         {
  167.             foreach (var node in Nodes)
  168.             {
  169.                 node.Value.DijkstraDistance = value;
  170.             }
  171.         }
  172.  
  173.         public double GetSumOfAllDijkstraDistance()
  174.         {
  175.             foreach (var item in Nodes)
  176.             {
  177.                 if (!visited.Contains(item.Value))
  178.                 {
  179.                     EmployDfs(item.Value);
  180.                 }
  181.             }
  182.             double sum = 0;
  183.             foreach (var node in Nodes)
  184.             {
  185.                 sum += node.Value.DijkstraDistance;
  186.             }
  187.  
  188.             return sum;
  189.         }
  190.  
  191.         public void EmployDfs(Node<T> node)
  192.         {
  193.             visited.Add(node);
  194.             foreach (var item in node.Connections)
  195.             {
  196.                 if (!visited.Contains(item.To))
  197.                 {
  198.                     EmployDfs(item.To);
  199.                 }
  200.                 node.DijkstraDistance += item.To.DijkstraDistance;
  201.             }
  202.  
  203.             if (node.DijkstraDistance == 0)
  204.             {
  205.                 node.DijkstraDistance++;
  206.             }
  207.         }
  208.  
  209.         public void EmployBfs(T nodeName)
  210.         {
  211.             Queue<Node<T>> nodes = new Queue<Node<T>>();
  212.             Node<T> node = Nodes[nodeName];
  213.             nodes.Enqueue(node);
  214.             while (nodes.Count != 0)
  215.             {
  216.                 Node<T> currentNode = nodes.Dequeue();
  217.                 currentNode.DijkstraDistance++;
  218.  
  219.                 foreach (var connection in Nodes[currentNode.Name].Connections)
  220.                 {
  221.                     nodes.Enqueue(connection.To);
  222.                 }
  223.             }
  224.         }
  225.  
  226.         public List<Edge<T>> PrimeMinimumSpanningTree(T startNodeName)
  227.         {
  228.             if (!Nodes.ContainsKey(startNodeName))
  229.             {
  230.                 throw new ArgumentOutOfRangeException(string.Format("{0} is not containing in the graph.", startNodeName));
  231.             }
  232.  
  233.             List<Edge<T>> mpdTree = new List<Edge<T>>();
  234.             PriorityQueue<Edge<T>> queue = new PriorityQueue<Edge<T>>();
  235.             Node<T> node = Nodes[startNodeName];
  236.             foreach (var edge in node.Connections)
  237.             {
  238.                 queue.Enqueue(edge);
  239.             }
  240.  
  241.             visited.Add(node);
  242.  
  243.             while (queue.Count > 0)
  244.             {
  245.                 Edge<T> edge = queue.Dequeue();
  246.  
  247.                 if (!visited.Contains(edge.To))
  248.                 {
  249.                     node = edge.To;
  250.                     visited.Add(node); //we "visit" this node
  251.                     mpdTree.Add(edge);
  252.                     foreach (var item in node.Connections)
  253.                     {
  254.                         if (!mpdTree.Contains(item))
  255.                         {
  256.                             if (!visited.Contains(item.To))
  257.                             {
  258.                                 queue.Enqueue(item);
  259.                             }
  260.                         }
  261.                     }
  262.                 }
  263.             }
  264.             visited.Clear();
  265.             return mpdTree;
  266.         }
  267.  
  268.         public override string ToString()
  269.         {
  270.             StringBuilder result = new StringBuilder();
  271.  
  272.             foreach (var node in this.Nodes)
  273.             {
  274.                 result.Append(node.Key + " -> ");
  275.  
  276.                 foreach (var conection in node.Value.Connections)
  277.                 {
  278.                     result.Append(conection.To + "-" + conection.Distance + " ");
  279.                 }
  280.  
  281.                 result.AppendLine();
  282.             }
  283.  
  284.             return result.ToString();
  285.         }
  286.     }
  287.  
  288.     public class Node<T> : IComparable
  289.     {
  290.         private readonly IList<Edge<T>> connectionsList;
  291.  
  292.         public T Name { get; private set; }
  293.  
  294.         public double DijkstraDistance { get; set; }
  295.  
  296.         public List<Node<T>> DijkstraPath { get; set; }
  297.  
  298.         internal IEnumerable<Edge<T>> Connections
  299.         {
  300.             get
  301.             {
  302.                 return connectionsList;
  303.             }
  304.         }
  305.  
  306.         public Node(T name)
  307.         {
  308.             Name = name;
  309.             connectionsList = new List<Edge<T>>();
  310.         }
  311.  
  312.         internal void AddConnection(Node<T> targetNode, double distance, bool twoWay)
  313.         {
  314.             if (targetNode == null)
  315.             {
  316.                 throw new ArgumentNullException("targetNode");
  317.             }
  318.  
  319.             if (targetNode == this)
  320.             {
  321.                 throw new ArgumentException("Node may not connect to itself.");
  322.             }
  323.  
  324.             if (distance < 0)
  325.             {
  326.                 throw new ArgumentException("Distance must be positive.");
  327.             }
  328.  
  329.             connectionsList.Add(new Edge<T>(this, targetNode, distance));
  330.             if (twoWay)
  331.             {
  332.                 targetNode.AddConnection(this, distance, false);
  333.             }
  334.         }
  335.  
  336.         public override string ToString()
  337.         {
  338.             return this.Name.ToString();
  339.         }
  340.  
  341.         public int CompareTo(object obj)
  342.         {
  343.             return this.DijkstraDistance.CompareTo((obj as Node<T>).DijkstraDistance);
  344.         }
  345.     }
  346.  
  347.     public class Edge<T> : IComparable
  348.     {
  349.         internal Node<T> From { get; private set; }
  350.  
  351.         internal Node<T> To { get; private set; }
  352.  
  353.         internal double Distance { get; private set; }
  354.  
  355.         internal Edge(Node<T> from, Node<T> to, double distance)
  356.         {
  357.             this.From = from;
  358.             this.To = to;
  359.             this.Distance = distance;
  360.         }
  361.  
  362.         public int CompareTo(object obj)
  363.         {
  364.             return this.Distance.CompareTo((obj as Edge<T>).Distance);
  365.         }
  366.  
  367.         public override string ToString()
  368.         {
  369.             return string.Format("({0} {1}) -> {2}", From, To, Distance);
  370.         }
  371.     }
  372.  
  373.     public class PriorityQueue<T> : IEnumerable
  374.         where T : IComparable
  375.     {
  376.         private readonly List<T> heap;
  377.  
  378.         public PriorityQueue()
  379.         {
  380.             heap = new List<T>();
  381.         }
  382.  
  383.         public PriorityQueue(int size)
  384.         {
  385.             heap = new List<T>(size);
  386.         }
  387.  
  388.         public int Count
  389.         {
  390.             get
  391.             {
  392.                 return this.heap.Count;
  393.             }
  394.         }
  395.  
  396.         public bool IsEmpty
  397.         {
  398.             get
  399.             {
  400.                 return this.heap.Count == 0;
  401.             }
  402.         }
  403.  
  404.         public void Enqueue(T item)
  405.         {
  406.             this.heap.Add(item);
  407.  
  408.             int childIndex = this.heap.Count - 1;
  409.             while (childIndex > 0)
  410.             {
  411.                 int parentIndex = (childIndex - 1) / 2;
  412.                 if (this.heap[parentIndex].CompareTo(this.heap[childIndex]) <= 0)
  413.                 {
  414.                     break;
  415.                 }
  416.  
  417.                 T swap = this.heap[childIndex];
  418.                 this.heap[childIndex] = this.heap[parentIndex];
  419.                 this.heap[parentIndex] = swap;
  420.  
  421.                 childIndex = parentIndex;
  422.             }
  423.         }
  424.  
  425.         public T Dequeue()
  426.         {
  427.             if (this.heap.Count == 0)
  428.             {
  429.                 throw new InvalidOperationException("Queue empty.");
  430.             }
  431.  
  432.             int lastIndex = this.heap.Count - 1;
  433.  
  434.             T topItem = this.heap[0];
  435.             this.heap[0] = this.heap[lastIndex];
  436.             this.heap.RemoveAt(lastIndex);
  437.             lastIndex--;
  438.  
  439.             int parentIndex = 0;
  440.             while (true)
  441.             {
  442.                 int leftIndex = 2 * parentIndex + 1;
  443.                 if (leftIndex > lastIndex)
  444.                 {
  445.                     break;
  446.                 }
  447.  
  448.                 int swapIndex = leftIndex;
  449.                 int rightIndex = leftIndex + 1;
  450.                 if (rightIndex <= lastIndex && this.heap[rightIndex].CompareTo(this.heap[leftIndex]) < 0)
  451.                 {
  452.                     swapIndex = rightIndex;
  453.                 }
  454.  
  455.                 if (this.heap[parentIndex].CompareTo(this.heap[swapIndex]) <= 0)
  456.                 {
  457.                     // the parent and the child are in order
  458.                     break;
  459.                 }
  460.  
  461.                 T swap = this.heap[swapIndex];
  462.                 this.heap[swapIndex] = this.heap[parentIndex];
  463.                 this.heap[parentIndex] = swap;
  464.  
  465.                 parentIndex = swapIndex;
  466.             }
  467.  
  468.             return topItem;
  469.         }
  470.  
  471.         public T Peek()
  472.         {
  473.             if (this.heap.Count == 0)
  474.             {
  475.                 throw new InvalidOperationException("Queue empty.");
  476.             }
  477.  
  478.             T topItem = this.heap[0];
  479.             return topItem;
  480.         }
  481.  
  482.         public void Clear()
  483.         {
  484.             this.heap.Clear();
  485.         }
  486.  
  487.         public IEnumerator<T> GetEnumerator()
  488.         {
  489.             return this.heap.GetEnumerator();
  490.         }
  491.  
  492.         IEnumerator IEnumerable.GetEnumerator()
  493.         {
  494.             return this.GetEnumerator();
  495.         }
  496.  
  497.         public T[] ToArray()
  498.         {
  499.             return this.heap.ToArray();
  500.         }
  501.  
  502.         public override string ToString()
  503.         {
  504.             return string.Join(", ", this.heap);
  505.         }
  506.     }
  507. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement