Balkan OI 2012 - Shortest Paths
Author: Andi Qu
General graph -> Tree
General graphs are inconvenient - let's try to turn this graph into a tree!
Run Dijkstra's algorithm from node to every other node and construct the "shortest path tree" from this (i.e. the tree made of the union of the shortest paths from node to each other node). Make sure to force the lucky path given in the input to be in this tree!
Why is this useful? In this case, we get some cool properties from removing edges on the lucky path.
What happens when we remove an edge?
When we remove an edge on the lucky path, the tree splits into two smaller trees - one containing ; one containing .
This means the shortest path must be of the form where and are two nodes joined by an edge and is in 's tree while is in 's tree.
Why is this true?
Firstly, any vertex is still connected to either via its shortest path tree or via its shortest path tree after a single edge on the shortest path is removed.
Secondly, we must "jump" from one subtree to the other at some point, so the new shortest paths must have two nodes in separate subtrees joined by an edge.
Updating the shortest paths
An important observation is that if you keep moving up from a node to its parent, you'll eventually reach a node on the lucky path. For node , let this node on the lucky path be . Since is so small, we can just naively find for each .
Since and must be in separate subtrees, the path is only a candidate for the shortest path after removing an edge if that edge lies between and .
We must thus only update the shortest paths after removing an edge for the edges between and for each edge .
Again, we can just naively update these shortest paths.
The final complexity of this algorithm is
Code
1#include <bits/stdc++.h>2typedef long long ll;3using namespace std;45struct Edge {6 int u, v;7 ll c;8} edges[200000];910bool operator<(Edge a, Edge b) {
Join the USACO Forum!
Stuck on a problem, or don't understand a module? Join the USACO Forum and get help from other competitive programmers!