/* * BrokerRumour * ACM practise contest problem * * Is just the shortest path! Cool. Dijkstra! * * Parke Godfrey, 25 Sept 2008 */ import java.io.PrintStream; import java.util.Scanner; class Node { public final int id; public int measure; public int inQ; public Node(int i) { id = i; measure = -1; } } /* * PriQ : Okay. I implemented my own so I could dynamically update * the priority in the queue when the distance is modified during * shortest path. Java's standard PriQueue does not offer that. * (Some other tree containers might...) In any case, not worth the * coding time in the contest. Just use Java's PriQueue with remove() * and add() for updating distances. That would be fast enough * for the program contest. */ class QBox { public Node node; public QBox(Node n) { node = n; } } class PriQ { private QBox[] queue; private int qEnd; public PriQ (Node[] nodes) { qEnd = nodes.length; queue = new QBox[qEnd]; for (int i = 0; i < qEnd; i++) { queue[i] = new QBox(nodes[i]); nodes[i].inQ = i; } } public boolean isEmpty() { if (qEnd > 0) return false; else return true; } public Node pop() { Node head = queue[0].node; swap(0, qEnd-1); qEnd--; perkDown(0); return head; } private void swap(int i, int j) { Node n = queue[i].node; queue[i].node = queue[j].node; queue[j].node = n; queue[i].node.inQ = i; queue[j].node.inQ = j; } public void update(Node node) { perkUp(node.inQ); } private void perkDown(int parent) { int left = (parent + 1)*2 - 1; int right = left + 1; if (left >= qEnd) return; if (((queue[parent].node.measure == -1) && (queue[left].node.measure != -1)) || ((queue[parent].node.measure > queue[left].node.measure) && (queue[left].node.measure != -1))) { swap(parent, left); perkDown(left); return; } if (right >= qEnd) return; if (((queue[parent].node.measure == -1) && (queue[right].node.measure != -1)) || ((queue[parent].node.measure > queue[right].node.measure) && (queue[right].node.measure != -1))) { swap(parent, right); perkDown(right); } } private void perkUp(int child) { if (child == 0) return; if (queue[child].node.measure == -1) return; int parent = (child - 1) / 2; if ((queue[parent].node.measure > queue[child].node.measure) || (queue[parent].node.measure == -1)) swap(parent, child); perkUp(parent); } } /* * BrokerRumour */ public class BrokerRumour { public static void main(String[] args) { Scanner input = new Scanner(System.in); PrintStream output = System.out; int brokerMax = input.nextInt(); while (brokerMax > 0) { int[][] connMat = new int[brokerMax][brokerMax]; // Initialize the connectivity matrix. for (int i = 0; i < brokerMax; i++) { for (int j = 0; j < brokerMax; j++) { connMat[i][j] = -1; } } int connNum; // Number of contacts that broker has. // Read in the connectivity weights into the matrix. for (int i = 0; i < brokerMax; i++) { connNum = input.nextInt(); for (int j = 0; j < connNum; j++) connMat[i][input.nextInt() - 1] = input.nextInt(); } Node[] nodes = new Node[brokerMax]; for (int i = 0; i < brokerMax; i++) nodes[i] = new Node(i); int bestStart = -1; int fastest = -1; // We'll do a Dijkstra's shortest path starting with each // broker in turn. for (int i = 0; i < brokerMax; i++) { for (int j = 0; j < brokerMax; j++) nodes[j].measure = -1; PriQ priQ = new PriQ(nodes); nodes[i].measure = 0; priQ.update(nodes[i]); Node head = null; while (!priQ.isEmpty()) { head = priQ.pop(); output.printf(" %d) %d: %d\n", i, head.id, head.measure); if (head.measure == -1) break; // I could tighten this. No need to test against // items already "marked" as done in Dijkstra's. // But I am not marking. They have shorter distances, // so no problem. But I waste extra comparisons. for (int j = 0; j < brokerMax; j++) { if ((j != head.id) && (connMat[head.id][j] != -1) && ((head.measure + connMat[head.id][j] < nodes[j].measure) || (nodes[j].measure == -1))) { nodes[j].measure = head.measure + connMat[head.id][j]; priQ.update(nodes[j]); } } } if ((head.measure != -1) && ((head.measure < fastest) || (fastest == -1))) { bestStart = i; fastest = head.measure; } } if (bestStart == -1) output.println("disjoint"); else output.printf("%d %d\n", bestStart+1, fastest); brokerMax = input.nextInt(); } } }