Advertisement
Mitrezzz

[АПС] Лаб 10: Алгоритми за графови Градови

Jan 6th, 2021
1,125
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 17.40 KB | None | 0 0
  1. import com.sun.jmx.remote.internal.ArrayQueue;
  2.  
  3. import java.io.BufferedReader;
  4. import java.io.IOException;
  5. import java.io.InputStreamReader;
  6. import java.util.*;
  7.  
  8.  
  9. import java.util.Iterator;
  10.  
  11.  
  12. class Edge{
  13.     private int fromVertex, toVertex;
  14.     private float weight;
  15.     public Edge(int from, int to, float weight){
  16.         this.fromVertex = from;
  17.         this.toVertex = to;
  18.         this.weight = weight;
  19.     }
  20.  
  21.     public int getFrom(){
  22.         return this.fromVertex;
  23.     }
  24.     public int getTo(){
  25.         return this.toVertex;
  26.     }
  27.     public float getWeight(){
  28.         return this.weight;
  29.     }
  30. }
  31.  
  32. class Graph<E> {
  33.  
  34.     int num_nodes;
  35.     GraphNode<E> adjList[];
  36.  
  37.     @SuppressWarnings("unchecked")
  38.     public Graph(int num_nodes, E[] list) {
  39.         this.num_nodes = num_nodes;
  40.         adjList = (GraphNode<E>[]) new GraphNode[num_nodes];
  41.         for (int i = 0; i < num_nodes; i++)
  42.             adjList[i] = new GraphNode<E>(i, list[i]);
  43.     }
  44.  
  45.     @SuppressWarnings("unchecked")
  46.     public Graph(int num_nodes) {
  47.         this.num_nodes = num_nodes;
  48.         adjList = (GraphNode<E>[]) new GraphNode[num_nodes];
  49.         for (int i = 0; i < num_nodes; i++)
  50.             adjList[i] = new GraphNode<E>(i, null);
  51.     }
  52.  
  53.     int adjacent(int x, int y) {
  54.         // proveruva dali ima vrska od jazelot so
  55.         // indeks x do jazelot so indeks y
  56.         return (adjList[x].containsNeighbor(adjList[y])) ? 1 : 0;
  57.     }
  58.  
  59.     void addEdge(int x, int y, float tezina) {
  60.         // dodava vrska od jazelot so indeks x do jazelot so indeks y so tezina
  61.         if (adjList[x].containsNeighbor(adjList[y])) {
  62.             adjList[x].updateNeighborWeight(adjList[y], tezina);
  63.         } else
  64.             adjList[x].addNeighbor(adjList[y], tezina);
  65.     }
  66.  
  67.     void deleteEdge(int x, int y) {
  68.         adjList[x].removeNeighbor(adjList[y]);
  69.     }
  70.  
  71.     /*************************** KRUSKAL ***********************************************************************/
  72.     // Metoda koja generira niza od site rebra vo grafot
  73.     public Edge[] getAllEdges() {
  74.         int totalEdges = 0;
  75.         for (int i = 0; i < this.num_nodes; i++) {
  76.             // za sekoe teme go dodavame brojot na sosedi koi gi ima
  77.             totalEdges += this.adjList[i].getNeighbors().size();
  78.         }
  79.  
  80.         // System.out.println("METODA: Imame vk "+totalEdges+" rebra");
  81.  
  82.         Edge[] edges = new Edge[totalEdges];
  83.         int index = 0;
  84.         for (int i = 0; i < this.num_nodes; i++) {
  85.             for (int j = 0; j < this.adjList[i].getNeighbors().size(); j++) {
  86.                 int index1 = this.adjList[i].getIndex();
  87.                 // se zemaat indeksot i tezinata na j-ot sosed na temeto i
  88.                 int index2 = this.adjList[i].getNeighbors().get(j).node
  89.                         .getIndex();
  90.                 float weight = this.adjList[i].getNeighbors().get(j).weight;
  91.                 edges[index++] = new Edge(index1, index2, weight);
  92.             }
  93.         }
  94.  
  95.         return edges;
  96.     }
  97.  
  98.     // Metoda koja gi sortira site rebra
  99.     private Edge[] sortEdges(Edge[] edges) {
  100.         for (int i = 0; i < edges.length - 1; i++) {
  101.             for (int j = i + 1; j < edges.length; j++) {
  102.                 if (edges[i].getWeight() > edges[j].getWeight()) {
  103.                     Edge tmp = edges[i];
  104.                     edges[i] = edges[j];
  105.                     edges[j] = tmp;
  106.                 }
  107.             }
  108.         }
  109.  
  110.         return edges;
  111.     }
  112.  
  113.     // Metoda koja pravi unija na dve drva
  114.     private int[] union(int u, int v, int[] vrski) {
  115.         int findWhat, replaceWith;
  116.  
  117.         if (u < v) {
  118.             findWhat = vrski[v];
  119.             replaceWith = vrski[u];
  120.         } else {
  121.             findWhat = vrski[u];
  122.             replaceWith = vrski[v];
  123.         }
  124.  
  125.         // za dvete poddrva stava ist index
  126.         // t.e. gi spojuva
  127.         for (int i = 0; i < vrski.length; i++) {
  128.             if (vrski[i] == findWhat) {
  129.                 vrski[i] = replaceWith;
  130.             }
  131.         }
  132.         return vrski;
  133.     }
  134.  
  135.     List<Edge> kruskal() {
  136.         /*
  137.          * Pomoshna niza za sledenje na kreiranite drva Ako dve teminja se del
  138.          * od isto poddrvo togash imaat ista vrednost vo nizata
  139.          */
  140.         int vrski[] = new int[this.num_nodes];
  141.  
  142.         // niza koja gi sodrzi site rebra
  143.         Edge[] edges = this.getAllEdges();
  144.         // se sortiraat rebrata spored tezinite vo neopagjacki redosled
  145.         edges = this.sortEdges(edges);
  146.  
  147.         // inicijalizacija na pomosnata niza za evidencija,
  148.         // sekoj jazel si e posebno drvo
  149.         for (int i = 0; i < this.num_nodes; i++)
  150.             vrski[i] = i;
  151.  
  152.         // lista koja kje gi sodrzi MST rebra
  153.         List<Edge> mstEdges = new ArrayList<Edge>();
  154.  
  155.         for (int i = 0; i < edges.length; i++) {
  156.             // za sekoe rebro vo sortiran redosled
  157.             Edge e = edges[i];
  158.  
  159.             if (vrski[e.getFrom()] != vrski[e.getTo()]) {
  160.                 // ako teminjata na ova rebro ne se vo isto poddrvo
  161.                 // ova rebro e MST rebro
  162.                 mstEdges.add(e);
  163.                 // sega dvete teminja treba da se vo isto poddrvo
  164.                 // t.e se pravi merge (unija) t.s. vo nizata vrski
  165.                 // za site elementi od dvete poddrva
  166.                 // go setira istiot (najmal) element od dvete poddrva
  167.                 vrski = this.union(e.getFrom(), e.getTo(), vrski);
  168.             }
  169.  
  170.             // ako sme dodale num_nodes-1 rebra moze da prestaneme
  171.             if (mstEdges.size() == (this.num_nodes - 1))
  172.                 break;
  173.         }
  174.  
  175.         return mstEdges;
  176.     }
  177.  
  178.     public void dfsVisit(boolean visited[], GraphNode<E> node, int end_node, float currCost, float[] dist, Stack<Integer> stack, Hashtable<Integer, String> ht){
  179.  
  180.         if(!visited[node.getIndex()] && node.getIndex() == end_node){
  181.  
  182.              // prevrti
  183.             Stack<Integer> s = new Stack<Integer>();
  184.             s.push(node.getIndex());
  185.             while(!stack.isEmpty()){
  186.                 s.push(stack.pop());
  187.             }
  188.  
  189.             // printaj
  190.             while(!s.isEmpty()){
  191.                 System.out.print(ht.get(s.pop()) + " ");
  192.             }
  193.             return;
  194.         }
  195.  
  196.         if(!visited[node.getIndex()]){
  197.  
  198.             visited[node.getIndex()] = true;
  199.             stack.push(node.getIndex());
  200.             LinkedList<GraphNodeNeighbor<E>> neigh = adjList[node.getIndex()].getNeighbors();
  201.             for(int i = 0; i < neigh.size(); i++){
  202.                 GraphNode<E> node1= neigh.get(i).node;
  203.                 float weight = neigh.get(i).weight;
  204.                 if(!visited[node1.getIndex()] && currCost + weight <= dist[end_node]){
  205.                     dfsVisit(visited,node1,end_node, currCost + weight, dist, stack, ht);
  206.                 }
  207.             }
  208.             if(!stack.isEmpty())
  209.                 stack.pop();
  210.  
  211.         }
  212.  
  213.     }
  214.  
  215.     public void printPath(Hashtable<Integer,String> ht, int start_node, int end_node){
  216.  
  217.         boolean visited[] = new boolean[this.num_nodes];
  218.         for(int i = 0; i < this.num_nodes; i++){
  219.             visited[i] = false;
  220.         }
  221.  
  222.         float dist[] = dijkstra(start_node);
  223.         Stack<Integer> stek = new Stack<>();
  224.         stek.push(start_node);
  225.         LinkedList<GraphNodeNeighbor<E>> index = adjList[start_node].getNeighbors();
  226.         for(int i = 0; i < index.size(); i++){
  227.             GraphNode<E> node = index.get(i).node;
  228.             float weight = index.get(i).weight;
  229.             if(!visited[node.getIndex()] && weight <= dist[end_node]){
  230.                 dfsVisit(visited,node, end_node, weight, dist, stek, ht);
  231.             }
  232.         }
  233.  
  234.     }
  235.  
  236.     /*******************************************************************************************************/
  237.  
  238.     /************************ PRIM **************************************************************************/
  239.  
  240.     // Metoda koja go naogja najmaloto rebro do
  241.     // teme na neposeten sosed
  242.     private Edge getMinimalEdge(boolean[] included) {
  243.         int index1 = Integer.MAX_VALUE, index2 = Integer.MAX_VALUE;
  244.         float minweight = Float.MAX_VALUE;
  245.  
  246.         for (int i = 0; i < this.num_nodes; i++) {
  247.             if (included[i]) {
  248.                 // ako e vkluceno temeto i
  249.                 // izmini gi negovite nevkluceni sosedi
  250.                 Iterator<GraphNodeNeighbor<E>> it = adjList[i].getNeighbors()
  251.                         .iterator();
  252.                 while (it.hasNext()) {
  253.                     GraphNodeNeighbor<E> pom = it.next();
  254.                     // ako sosedot ne e poseten i ima do sega najmala tezina
  255.                     if (!included[pom.node.getIndex()]
  256.                             && pom.weight < minweight) {
  257.                         index1 = i;
  258.                         index2 = pom.node.getIndex();
  259.                         minweight = pom.weight;
  260.                     }
  261.                 }
  262.             }
  263.         }
  264.  
  265.         if (minweight < Float.MAX_VALUE) {
  266.             Edge ret = new Edge(index1, index2, minweight);
  267.             return ret;
  268.         }
  269.         return null;
  270.     }
  271.  
  272.     List<Edge> prim(int start_index) {
  273.         // lista koja kje gi sodrzi MST rebra
  274.         List<Edge> mstEdges = new ArrayList<Edge>();
  275.  
  276.         boolean included[] = new boolean[this.num_nodes];
  277.         for (int i = 0; i < this.num_nodes; i++)
  278.             included[i] = false;
  279.  
  280.         included[start_index] = true;
  281.  
  282.         for (int i = 0; i < this.num_nodes - 1; i++) {
  283.             Edge e = this.getMinimalEdge(included);
  284.             if (e == null) {
  285.                 System.out.println("Ne mozat da se povrzat site jazli");
  286.                 break;
  287.             }
  288.             included[e.getFrom()] = included[e.getTo()] = true;
  289.             mstEdges.add(e);
  290.         }
  291.  
  292.         return mstEdges;
  293.     }
  294.  
  295.     /*******************************************************************************************************/
  296.     /***************** DIJKSTRA ******************************************************************************/
  297.  
  298.     float[] dijkstra(int from) {
  299.  
  300.         /* Minimalna cena do sekoj od teminjata */
  301.         float distance[] = new float[this.num_nodes];
  302.         /* dali za temeto e najdena konecnata (minimalna) cena */
  303.         boolean finalno[] = new boolean[this.num_nodes];
  304.         for (int i = 0; i < this.num_nodes; i++) {
  305.             distance[i] = -1;
  306.             finalno[i] = false;
  307.         }
  308.  
  309.         finalno[from] = true;
  310.         distance[from] = 0;
  311.  
  312.         /*
  313.          * vo sekoj cekor za edno teme se dobiva konecna minimalna cena
  314.          */
  315.         for (int i = 1; i < this.num_nodes; i++) {
  316.             /* za site sledbenici na from presmetaj ja cenata */
  317.             Iterator<GraphNodeNeighbor<E>> it = adjList[from].getNeighbors()
  318.                     .iterator();
  319.             while (it.hasNext()) {
  320.                 GraphNodeNeighbor<E> pom = it.next();
  321.                 /* ako grankata kon sosedot nema konecna cena */
  322.                 if (!finalno[pom.node.getIndex()]) {
  323.                     /* ako ne e presmetana cena za temeto */
  324.                     if (distance[pom.node.getIndex()] <= 0) {
  325.                         distance[pom.node.getIndex()] = distance[from]
  326.                                 + pom.weight;
  327.                     }
  328.                     /* inaku, ako e pronajdena poniska */
  329.                     else if (distance[from] + pom.weight < distance[pom.node
  330.                             .getIndex()]) {
  331.                         distance[pom.node.getIndex()] = distance[from]
  332.                                 + pom.weight;
  333.                     }
  334.                 }
  335.             }
  336.  
  337.             /* najdi teme so min. cena koja ne e konecna */
  338.             boolean minit = false; /* min. ne e inicijaliziran */
  339.             int k = -1;
  340.             float minc = -1;
  341.             /* proveri gi site teminja */
  342.             for (int j = 0; j < this.num_nodes; j++) {
  343.                 if (!finalno[j] && distance[j] != -1) { /*ako cenata ne e  konecna*/
  344.                     if (!minit) { /* ako ne e inicijaliziran minimumot */
  345.                         minc = distance[k = j]; /* proglasi go ova e minimum */
  346.                         minit = true; /* oznaci deka min e inicijaliziran */
  347.                     }
  348.                     /* proveri dali e pronajdeno teme so pomala cena */
  349.                     else if (minc > distance[j] && distance[j] > 0)
  350.                         minc = distance[k = j];
  351.                 }
  352.             }
  353.             finalno[from = k] = true;
  354.         }
  355.  
  356.         return distance;
  357.  
  358.     }
  359.  
  360.     /*******************************************************************************************************/
  361.  
  362.     @Override
  363.     public String toString() {
  364.         String ret = new String();
  365.         for (int i = 0; i < this.num_nodes; i++)
  366.             ret += adjList[i] + "\n";
  367.         return ret;
  368.     }
  369.  
  370. }
  371.  
  372. class GraphNode<E> {
  373.     private int index; //index (reden broj) na temeto vo grafot
  374.     private E info;
  375.     private LinkedList<GraphNodeNeighbor<E>> neighbors;
  376.  
  377.     public GraphNode(int index, E info) {
  378.         this.index = index;
  379.         this.info = info;
  380.         neighbors = new LinkedList<GraphNodeNeighbor<E>>();
  381.     }
  382.  
  383.     public boolean containsNeighbor(GraphNode<E> o){
  384.         GraphNodeNeighbor<E> pom = new GraphNodeNeighbor<E>(o,0);
  385.         return neighbors.contains(pom);
  386.     }
  387.  
  388.     public void addNeighbor(GraphNode<E> o, float weight){
  389.         GraphNodeNeighbor<E> pom = new GraphNodeNeighbor<E>(o,weight);
  390.         neighbors.add(pom);
  391.     }
  392.  
  393.     public void removeNeighbor(GraphNode<E> o){
  394.         GraphNodeNeighbor<E> pom = new GraphNodeNeighbor<E>(o,0);
  395.         if(neighbors.contains(pom))
  396.             neighbors.remove(pom);
  397.     }
  398.  
  399.     @Override
  400.     public String toString() {
  401.         String ret= "INFO:"+info+" SOSEDI:";
  402.         for(int i=0;i<neighbors.size();i++)
  403.             ret+="("+neighbors.get(i).node.info+","+neighbors.get(i).weight+") ";
  404.         return ret;
  405.  
  406.     }
  407.  
  408.     public void updateNeighborWeight(GraphNode<E> o, float weight){
  409.         Iterator<GraphNodeNeighbor<E>> i = neighbors.iterator();
  410.         while(i.hasNext()){
  411.             GraphNodeNeighbor<E> pom = i.next();
  412.             if(pom.node.equals(o))
  413.                 pom.weight = weight;
  414.         }
  415.  
  416.     }
  417.  
  418.     @Override
  419.     public boolean equals(Object obj) {
  420.         @SuppressWarnings("unchecked")
  421.         GraphNode<E> pom = (GraphNode<E>)obj;
  422.         return (pom.info.equals(this.info));
  423.     }
  424.  
  425.     public int getIndex() {
  426.         return index;
  427.     }
  428.  
  429.     public void setIndex(int index) {
  430.         this.index = index;
  431.     }
  432.  
  433.     public E getInfo() {
  434.         return info;
  435.     }
  436.  
  437.     public void setInfo(E info) {
  438.         this.info = info;
  439.     }
  440.  
  441.     public LinkedList<GraphNodeNeighbor<E>> getNeighbors() {
  442.         return neighbors;
  443.     }
  444.  
  445.     public void setNeighbors(LinkedList<GraphNodeNeighbor<E>> neighbors) {
  446.         this.neighbors = neighbors;
  447.     }
  448.  
  449.  
  450.  
  451. }
  452.  
  453. class GraphNodeNeighbor<E> {
  454.     GraphNode<E> node;
  455.     float weight;
  456.  
  457.     public GraphNodeNeighbor(GraphNode<E> node, float weight) {
  458.         this.node = node;
  459.         this.weight = weight;
  460.     }
  461.  
  462.     public GraphNodeNeighbor(GraphNode<E> node) {
  463.         this.node = node;
  464.         this.weight = 0;
  465.     }
  466.  
  467.     @Override
  468.     public boolean equals(Object obj) {
  469.         @SuppressWarnings("unchecked")
  470.         GraphNodeNeighbor<E> pom = (GraphNodeNeighbor<E>)obj;
  471.         return pom.node.equals(this.node);
  472.     }
  473.  
  474.  
  475.  
  476.  
  477.  
  478. }
  479.  
  480. public class Cities {
  481.  
  482.  
  483.  
  484.     public static void main(String []args) throws IOException {
  485.  
  486.         BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
  487.         int n = Integer.parseInt(in.readLine());
  488.         int num_edges = Integer.parseInt(in.readLine());
  489.         Hashtable<String, Integer> gradovi = new Hashtable<>(n+1);
  490.         Hashtable< Integer, String > reverse = new Hashtable<>(n+1);
  491.         Graph<Integer> g = new Graph<>(n);
  492.  
  493.         for(int i = 0; i < num_edges; i++){
  494.  
  495.             String line = in.readLine();
  496.             String pom[] = line.split(" ");
  497.  
  498.             int index1 = Integer.parseInt(pom[0]);
  499.             int index2 = Integer.parseInt(pom[2]);
  500.  
  501.             String grad1 = pom[1];
  502.             String grad2 = pom[3];
  503.             float dist = Float.parseFloat(pom[4]);
  504.  
  505.  
  506.             if(!gradovi.contains(grad1)){
  507.                 gradovi.put(grad1,index1);
  508.                 reverse.put(index1,grad1);
  509.  
  510.             }
  511.  
  512.             if(!gradovi.contains(grad2)){
  513.                 gradovi.put(grad2,index2);
  514.                 reverse.put(index2,grad2);
  515.             }
  516.  
  517.             g.adjList[index1].setInfo(index1);
  518.             g.adjList[index2].setInfo(index2);
  519.  
  520.             g.addEdge(index1,index2,dist);
  521.  
  522.         }
  523.  
  524.         String grad1 = in.readLine();
  525.         int index1 = gradovi.get(grad1);
  526.         String grad2 = in.readLine();
  527.         int index2 = gradovi.get(grad2);
  528.  
  529.         float sum = 0;
  530.         float dijk1[] = g.dijkstra(index1);
  531.         float dijk2[] = g.dijkstra(index2);
  532.  
  533.         sum += dijk1[index2];
  534.         sum += dijk2[index1];
  535.  
  536.  
  537.         g.printPath(reverse,index1, index2);
  538.         System.out.println();
  539.         g.printPath(reverse, index2, index1);
  540.         System.out.println();
  541.         System.out.println(sum);
  542.         // todo: implement the function which prints the path
  543.  
  544.     }
  545. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement