I have an undirected, unweighted graph. Let us fix a vertex and find all distinct paths from that vertex which covers all vertices of the graph. The task is to find the number of possible such paths from every vertices.
Eg: Let us take a graph of 4 vertices [ 1, 2, 3, 4]. And the edges are (1,2), (2,3), (3,4), (4,2). Here answer is 4. The paths are 1>2>3>4, 1>2>4>3, 3>4>2>1, 4>3>2>1.
I have come with an algorithm which uses brute-force technique to find the number of possible such paths, initialized by each vertex.Eg:
For the above example:
From vertex 1 there is 2 such path;
From vertex 2 there is no such path;
From vertex 3 there is 1 such path;
From vertex 4 there is 1 such path;
So the answer is 2+1+1=4.
Is it possible to solve this problem in a better time complexity?
There's an O(2^n n^2)-time algorithm obtained by modifying the Held--Karp DP. The idea is, for each subset S of vertices paired with some endpoint t in S, compute the number of paths that visit exactly the vertices in S and end at t by summing, for each neighbor u of t that is in S, the count for visiting S - {t} and ending at u. As a base case, the singleton sets all have count 1. In Python 3:
import itertools
def count_hamilton_paths(graph): # graph is a dict of adjacency lists
vertices = frozenset(graph)
table = {(frozenset({t}), t): 1 for t in vertices}
for r in range(2, len(vertices) + 1):
for subset_tuple in itertools.combinations(vertices, r):
subset = frozenset(subset_tuple)
for t in subset:
subset_minus_t = subset - frozenset({t})
table[(subset, t)] = sum(table[(subset_minus_t, u)]
for u in graph[t]
if u in subset_minus_t)
return sum(table[(vertices, t)] for t in vertices)
print(count_hamilton_paths({1: {2}, 2: {1, 3, 4}, 3: {2, 4}, 4: {2, 3}}))
Related
My job is to generate a random undirected, unweighted graph with a given diameter d. What I did already is to generate a random distance matrix D where each element Dij represents the distance between the i-th and j-th vertices of the graph. So, basically I am doing this:
if (i == j) {
D[i][j] = 0;
} else {
D[i][j] = D[j][i] = random.nextInt(d + 1);
}
The diagonal is zero because it always needs zero effort to reach the same vertex, am I right?
Also, Dij = Dji because it is undirected. Are my assumptions right?
I want to use java, but I tagged the question as language-agnostic because I need an algorithm and not a code.
My next step is to use Dijkstra's algorithm to generate a random graph by generating an adjacency matrix. I think that Dijkstra's algorithm is to find the shortest path, but can I use it for my case?
EDIT #1:
As you can see in the figure above, the diameter is 4 because the most distanced vertices are 2 and 7 have a distance of 4. For that reason, we have D[2][7] = D[7][2] = 4. Another example is D[3][6] = D[6][3] = 2, because if we want to go from 3 to 6, we can go 3 -> 5 -> 6, or 3 -> 1 -> 6 and vice versa for going from 6 to 3.
What I am looking for is to generate a random graph by knowing the diameter which is the maximum distance between two vertices in the graph. I know there are a lot of possibilities of the graph, but I need any of them.
I have an idea which is assuming that the number of vertices is d + 1, then connecting each vertex to the following vertex. In this case we will have a linear graph.
Example (diameter = 2, number of vertices = 3):
v
1
2
3
1
0
1
2
2
1
0
1
3
2
1
0
The diagonal = zero
D1,2 = D2,1 = D2,3 = D3,2 = 1, because to go from 1 to 2, or 2 to 3, there is a direct link
D1,3 = D3,1 = 2, because to go from 1 to 3, the shortest path is 1
-> 2 -> 3
Here is the graph associated to the above distance matrix:
I am looking for a better approach.
Given an undirected and connected graph of N vertices and N-1 edges. The number written on the ith vertex is val[i]. The task is to count the number of pairs (x, y) such that following conditions are satisfied:
0 ≤ x < y ≤ N-1
The GCD of the numbers written on the vertices on the simple path in the given graph from x to
y should be divisible by K.
Example:
Input:
N = 4, K = 2
Edges[] = {{0, 1}, {0, 2}, {2, 3}}
Val[] = {2, 6, 4, 3}
Output:
3
Explanation:
0 - 1
|
2 - 3
There are three pairs - (0,1), (1,2) and
(0,2) which satisify both the conditions.
There are two observations here:
1)It is a connected graph and it has n-1 edges. So it has to be a tree.
2)For condition 2 to be true, all the numbers written on the nodes in the simple path between x and y has to be k or a multiple of k.
With these two observations we can devise a solution
Replace all val[i]'s with val[i]%k.
Foreach i from 0 to n-1:
a. if val[i]==0, and not visited before Run a dfs from node i.
b. In dfs only visit the nodes for which val[node]=0 and not visited before. Return the number of nodes you visited on this run. Let this number be x. Also mark these nodes visited.
c. Add xC2 = (x*(x-1))/2 to the answer. (Why? because all the pairs of these visited nodes satisfies both of our conditions. We can select 2 nodes in xC2 ways.).
Algorithm:
For each edge (u, v) in the Adjacency list:
If u and v do not belong to the same set:
Union(u, v)
else:
return true // cycle detected
return false
Graph:
(1)-------(2)
Adjacency List:
[1] -> [2]
[2] -> [1]
Disjoint-Sets:
{{1}, {2}}
Iteration 1:
Edge e = (1, 2)
Union(1, 2)
Disjoint Sets = {{1, 2}}
Iteration 2:
Edge e = (2, 1)
Both 2 and 1 belong to the same set, so the algorithm detects a cycle.
It is obvious that the graph does not contain a cycle.
The algorithm works flawlessly for directed graphs. Please help me with this analysis.
A cycle must have distinct edges! In union find algorithm, you iterate through all the edges. You would need to filter out the duplicate edges from adjacency list. In your case, there is only one iteration so it would return false.
I'm having a trouble finding a contradicting example of the next variation of the TSP problem.
Input: G=(V,E) undirected complete graph which holds the triangle inequality, w:E->R+ weight function, and a source vertex s.
Output: Simple Hamilton cycle that starts and ends at s, with a minimum weight.
Algorithm:
1. S=Empty-Set
2. B=Sort E by weights.
3. Initialized array M of size |V|,
where each cell in the array holds a counter (Initialized to 0)
and a list of pointers to all the edges of that vertex (In B).
4. While |S|!=|V|-1
a. e(u,v)=removeHead(B).
b. If e does not close a cycle in S then
i. s=s union {e}
ii. Increase degree counter for u,v.
iii. If M[u].deg=2 then remove all e' from B s.t e'=(u,x).
iv. If M[v].deg=2 then remove all e' from B s.t e'=(v,x).
5. S=S union removeHead(B).
This will be done similar to the Kruskal Algorithm (Using union-find DS).
Steps 4.b.iii and 4.b.iv will be done using the List of pointers.
I highly doubt that this algorithm is true so I instantly turned into finding why it is wrong. Any help would be appreciated.
Lets say we have a graph with 4 vertices (a, b, c, d) with edge weights as follows:
w_ab = 5
w_bc = 6
w_bd = 7
w_ac = 8
w_da = 11
w_dc = 12
7
|--------------|
5 | 6 12 |
a ---- b ---- c ----- d
|______________| |
| 8 |
|_____________________|
11
The triangle inequality holds for each triangle in this graph.
Your algorithm will choose the cycle a-b-c-d-a (cost 34), when a better cycle is a-b-d-c-a (cost 32).
Your procedure may not terminate. Consider a graph with nodes { 1, 2, 3, 4 } and edges { (1,2), (1,3), (2,3), (2,4), (3,4) }. The only Hamiltonian cycle in this graph is { (1,2), (1,3), (2,4), (3,4) }. Suppose the lowest weighted edge is (2,3). Then your procedure will pick (2,3), pick one of { (1,2), (1,3) } and eliminate the other, pick one of { (2,4), (3,4) } and eliminate the other, then loop forever.
Nuances like this are what makes the Travelling Salesman problem so difficult.
Consider the complete graph on 4 vertices, where {a,b,c,d} are the nodes, imagined as the clockwise arranged corners of a square. Let the edge weights be as follows.
w({a,b}) := 2, // "edges"
w({b,c}) := 2,
w({c,d}) := 2,
w({d,a}) := 2,
w({a,c}) := 1, // "diagnoals"
w({b,d}) := M
where M is an integer larger than 2. On one hand, the hamiltonian cycle consisting of the "edges" has weight 8. On the other hand, the hamiltonian cycle containing {a,c} , which is the lightest edge, must contain {b,d} and has total weight
1 + M + 2 + 2 = 5 + M > 8
which is larger than the minimum possible weight. In total, this means that in general a hamitonian cycle of minimum weight does not necessarily contain the lightst edge, which is chosen by the algorithm in the original question. Furthermore, as M tends to infinity, the algorithm performs arbitrarily badly in terms of the approximation ratio, as
(5 + M) / 8
grows arbitrarily large.
How do I, other than brute forcing, efficiently draw a correct Complete 5-Vertex Undirected Graph with distinct edge weights {1, 2, 3, 4, 5, 6, 7, 8, 9, 10} that satisfies the Triangle inequality? I'm unaware of any algorithm that exists to generate a correct graph G for the edge weights provided.
Here's an example of a Complete 5-Vertex Graph
Here's one that works.
(2,1): 1
(3,1): 2
(3,2): 3
(4,1): 4
(4,2): 5
(4,3): 6
(5,1): 7
(5,2): 8
(5,3): 9
(5,4): 10
The generalization to an n-vertex complete graph should be clear. The proof of correctness is inductive. For n = 0, it's obvious. For higher n, the inductive hypothesis is equivalent to the proposition that every violation of the triangle inequality involves vertex n. The edges involving vertex n are longer than the others, so n is not the transit vertex of a violation. Thus every hypothetical violation (up to symmetry) looks like n -> v -> w. There exists some constant c such that n -> v has length c + v and n -> w has length c + w. Hence, if v -> w is a violation, then it has length less than w - v, which, by inspection, is impossible.