algorithms graph theory shortest path dynamic programming complexity analysis data structures python java