What are Weighted and Unweighted Graphs?
- Unweighted Graphs: Edges represent simple connections with no associated value. Every connection has the same “cost” (implicitly 1).
- Weighted Graphs: Edges have numerical values (weights) representing costs, distances, travel times, or capacities between vertices.
Explanation
- Edge weights transform how we find paths and structure graphs. For instance, finding the shortest path changes from simple edge counts to minimizing total cumulative edge weights.
Real-World Analogy
- Unweighted Graph (Subway Map Index): A simple subway map where you only care about which stations are connected by a line. Each stop is counted as “1 step” regardless of the physical distance between stations.
- Weighted Graph (Road Network Navigation): A highway map showing the physical distance (in miles) or travel time (in minutes) between cities. A path with 2 edges (e.g. 50 miles + 60 miles = 110 miles) is preferred over a path with 1 edge of 150 miles.
- Logistics & Shipping: A supply chain graph where edges represent shipping routes and weights represent shipping costs or transport capacity.
How It Works
Core Mechanics
- Edge weights require adjustments to our standard graph representations:
1. Adjacency List Representation
- Instead of storing just the neighbor index
vin the list, we store a pair:(v, weight). - Example:
Adj[u] = [(v1, w1), (v2, w2)]
2. Adjacency Matrix Representation
- Instead of cell values of
0and1:Matrix[u][v] = weightif an edge exists.- If no edge exists:
- In Shortest Path contexts: Store $\infty$ (infinity) to represent unreachable paths.
- In Max Flow / Capacity contexts: Store
0to represent zero capacity. - In generic contexts: Store
Noneor-1(if weights are strictly positive).
3. Edge List Representation
- Each edge is stored as a tuple/triplet:
(u, v, weight).
Algorithmic Context
- Adding edge weights changes the algorithm selected for routing and connectivity:
Shortest Path
- Unweighted Graphs: Breadth First Search (BFS) finds the shortest path in $O(V + E)$ time.
- Weighted Graphs (Positive Weights): Dijkstras-algorithm calculates shortest paths in $O((V+E)\log V)$ time.
- Weighted Graphs (Negative Weights): Bellman Ford Algorithm must be used ($O(VE)$) to avoid infinite loops in negative cycles.
Minimum Spanning Tree (MST)
- Weighted graphs are used to construct Minimum Spanning Trees (connecting all nodes with the minimum sum of edge weights) using prims-algorithm or kruskals-algorithm.
Visual Walkthrough
Simple Weighted Graph (Undirected)
(5)
0 ----- 1
| /
(10)| / (2)
| /
2
Adjacency Matrix (using $\infty$ for no edge)
0 1 2
0 [ 0, 5, 10]
1 [ 5, 0, 2]
2 [ 10, 2, 0]
Adjacency List
0 -> [(1, 5), (2, 10)]
1 -> [(0, 5), (2, 2)]
2 -> [(0, 10), (1, 2)]
Time & Space Complexity
| Representation | Space Complexity | Neighbor Query Time | Edge Query $(u, v)$ |
|---|---|---|---|
| Weighted Adjacency List | $O(V + E)$ | $O(\text{degree}(u))$ | $O(\text{degree}(u))$ |
| Weighted Adjacency Matrix | $O(V^2)$ | $O(V)$ | $O(1)$ |
| Weighted Edge List | $O(E)$ | $O(E)$ | $O(E)$ |
Implementation
import math
# 1. WEIGHTED ADJACENCY LIST REPRESENTATION
class WeightedGraphList:
def __init__(self, num_vertices):
self.V = num_vertices
self.adj_list = [[] for _ in range(num_vertices)] # Stores (neighbor, weight) pairs
def add_edge(self, u, v, weight, directed=False):
self.adj_list[u].append((v, weight))
if not directed:
self.adj_list[v].append((u, weight))
def get_neighbors(self, u):
"""Returns list of (neighbor, weight) tuples."""
return self.adj_list[u]
def print_graph(self):
for u in range(self.V):
print(f"{u} -> {self.adj_list[u]}")
# 2. WEIGHTED ADJACENCY MATRIX REPRESENTATION
class WeightedGraphMatrix:
def __init__(self, num_vertices):
self.V = num_vertices
# Initialize matrix with infinity for non-existent paths, 0 for self-loops
self.matrix = [[math.inf] * num_vertices for _ in range(num_vertices)]
for i in range(num_vertices):
self.matrix[i][i] = 0
def add_edge(self, u, v, weight, directed=False):
self.matrix[u][v] = weight
if not directed:
self.matrix[v][u] = weight
def get_weight(self, u, v):
return self.matrix[u][v]
def print_graph(self):
for row in self.matrix:
formatted_row = [str(x) if x != math.inf else "INF" for x in row]
print(" ".join(formatted_row))#include <iostream>
#include <vector>
#include <limits>
// 1. WEIGHTED ADJACENCY LIST REPRESENTATION
class WeightedGraphList {
private:
int V;
// Stores pair of (neighbor, weight)
std::vector<std::vector<std::pair<int, double>>> adjList;
public:
WeightedGraphList(int vertices) : V(vertices), adjList(vertices) {}
void addEdge(int u, int v, double weight, bool directed = false) {
adjList[u].push_back({v, weight});
if (!directed) {
adjList[v].push_back({u, weight});
}
}
const std::vector<std::pair<int, double>>& getNeighbors(int u) const {
return adjList[u];
}
void printGraph() const {
for (int i = 0; i < V; ++i) {
std::cout << i << " -> [";
for (size_t j = 0; j < adjList[i].size(); ++j) {
std::cout << "(" << adjList[i][j].first << ", " << adjList[i][j].second << ")";
if (j + 1 < adjList[i].size()) std::cout << ", ";
}
std::cout << "]\n";
}
}
};
// 2. WEIGHTED ADJACENCY MATRIX REPRESENTATION
class WeightedGraphMatrix {
private:
int V;
double INF_VAL;
std::vector<std::vector<double>> matrix;
public:
WeightedGraphMatrix(int vertices) : V(vertices), INF_VAL(std::numeric_limits<double>::infinity()) {
matrix.assign(V, std::vector<double>(V, INF_VAL));
for (int i = 0; i < V; ++i) {
matrix[i][i] = 0;
}
}
void addEdge(int u, int v, double weight, bool directed = false) {
matrix[u][v] = weight;
if (!directed) {
matrix[v][u] = weight;
}
}
double getWeight(int u, int v) const {
return matrix[u][v];
}
void printGraph() const {
for (int i = 0; i < V; ++i) {
for (int j = 0; j < V; ++j) {
if (matrix[i][j] == INF_VAL) {
std::cout << "INF ";
} else {
std::cout << matrix[i][j] << " ";
}
}
std::cout << "\n";
}
}
};
When to Use
✅ Use Weighted Graphs When:
- You are modeling physical networks where distances or travel times vary (e.g. GPS, shipping, routing protocols like OSPF).
- Edges have capacities, such as bandwidth in telecom channels or flow volume in water pipes.
✅ Use Unweighted Graphs When:
- Only connectivity or reachability matters (e.g. tracking followers on social networks, check-ins, or solving simple mazes).
- Every link has an identical cost, making BFS the faster and simpler shortest-path solution.
Variations & Related Concepts
- Negative Edge Weights: Edges with negative values. If a cycle exists where the sum of weights is negative, it’s a negative cycle. Pathfinding algorithms will fail to terminate or yield infinite negative costs unless handled by Bellman Ford Algorithm.
- Flow Networks: Directed, weighted graphs where weights represent maximum capacities. Solved using Ford-Fulkerson or Edmonds-Karp algorithms.
Key Takeaways
- Unweighted graphs represent uniform connections, while weighted graphs assign costs, lengths, or capacities to edges.
- Weighted adjacency lists store tuples
(neighbor, weight). - Weighted adjacency matrices use $\infty$ (for shortest path) or $0$ (for flow) to represent non-existent edges.
- Shortest path calculations on weighted graphs require Dijkstra’s or Bellman-Ford, as standard BFS will fail to yield correct results.
- MST algorithms (Prim’s, Kruskal’s) require weighted graphs to optimize structural connection costs.