Karp’s minimum mean (or average) weight cycle algorithm
Last Updated :
20 Feb, 2023
Given a directed and strongly connected graph with non-negative edge weights. We define the mean weight of a cycle as the summation of all the edge weights of the cycle divided by the no. of edges. Our task is to find the minimum mean weight among all the directed cycles of the graph.
Example:
Input : Below Graph
Output : 1.66667
Method to find the smallest mean weight value cycle efficiently
Step 1: Choose first vertex as source.
Step 2: Compute the shortest path to all other vertices
on a path consisting of k edges 0 <= k <= V
where V is number of vertices.
This is a simple dp problem which can be computed
by the recursive solution
dp[k][v] = min(dp[k][v], dp[k-1][u] + weight(u,v)
where v is the destination and the edge(u,v) should
belong to E
Step 3: For each vertex calculate max(dp[n][v]-dp[k][v])/(n-k)
where 0<=k<=n-1
Step 4: The minimum of the values calculated above is the
required answer.
Please refer to the solution of problem 9.2 here for proof that the above steps find minimum average weight.
Implementation:
C++
#include<bits/stdc++.h>
using namespace std;
const int V = 4;
struct edge
{
int from, weight;
};
vector <edge> edges[V];
void addedge( int u, int v, int w)
{
edges[v].push_back({u, w});
}
void shortestpath( int dp[][V])
{
for ( int i=0; i<=V; i++)
for ( int j=0; j<V; j++)
dp[i][j] = -1;
dp[0][0] = 0;
for ( int i=1; i<=V; i++)
{
for ( int j=0; j<V; j++)
{
for ( int k=0; k<edges[j].size(); k++)
{
if (dp[i-1][edges[j][k].from] != -1)
{
int curr_wt = dp[i-1][edges[j][k].from] +
edges[j][k].weight;
if (dp[i][j] == -1)
dp[i][j] = curr_wt;
else
dp[i][j] = min(dp[i][j], curr_wt);
}
}
}
}
}
double minAvgWeight()
{
int dp[V+1][V];
shortestpath(dp);
double avg[V];
for ( int i=0; i<V; i++)
avg[i] = -1;
for ( int i=0; i<V; i++)
{
if (dp[V][i] != -1)
{
for ( int j=0; j<V; j++)
if (dp[j][i] != -1)
avg[i] = max(avg[i],
(( double )dp[V][i]-dp[j][i])/(V-j));
}
}
double result = avg[0];
for ( int i=0; i<V; i++)
if (avg[i] != -1 && avg[i] < result)
result = avg[i];
return result;
}
int main()
{
addedge(0, 1, 1);
addedge(0, 2, 10);
addedge(1, 2, 3);
addedge(2, 3, 2);
addedge(3, 1, 0);
addedge(3, 0, 8);
cout << minAvgWeight();
return 0;
}
|
Java
import java.io.*;
import java.util.*;
class GFG
{
static int V = 4 ;
static class Edge
{
int from, weight;
Edge( int from, int weight)
{
this .from = from;
this .weight = weight;
}
}
static Vector<Edge>[] edges = new Vector[V];
static
{
for ( int i = 0 ; i < V; i++)
edges[i] = new Vector<>();
}
static void addedge( int u, int v, int w)
{
edges[v].add( new Edge(u, w));
}
static void shortestpath( int [][] dp)
{
for ( int i = 0 ; i <= V; i++)
for ( int j = 0 ; j < V; j++)
dp[i][j] = - 1 ;
dp[ 0 ][ 0 ] = 0 ;
for ( int i = 1 ; i <= V; i++)
{
for ( int j = 0 ; j < V; j++)
{
for ( int k = 0 ; k < edges[j].size(); k++)
{
if (dp[i - 1 ][edges[j].elementAt(k).from] != - 1 )
{
int curr_wt = dp[i - 1 ][edges[j].elementAt(k).from] +
edges[j].elementAt(k).weight;
if (dp[i][j] == - 1 )
dp[i][j] = curr_wt;
else
dp[i][j] = Math.min(dp[i][j], curr_wt);
}
}
}
}
}
static double minAvgWeight()
{
int [][] dp = new int [V + 1 ][V];
shortestpath(dp);
double [] avg = new double [V];
for ( int i = 0 ; i < V; i++)
avg[i] = - 1 ;
for ( int i = 0 ; i < V; i++)
{
if (dp[V][i] != - 1 )
{
for ( int j = 0 ; j < V; j++)
if (dp[j][i] != - 1 )
avg[i] = Math.max(avg[i],
(( double ) dp[V][i] -
dp[j][i]) / (V - j));
}
}
double result = avg[ 0 ];
for ( int i = 0 ; i < V; i++)
if (avg[i] != - 1 && avg[i] < result)
result = avg[i];
return result;
}
public static void main(String[] args)
{
addedge( 0 , 1 , 1 );
addedge( 0 , 2 , 10 );
addedge( 1 , 2 , 3 );
addedge( 2 , 3 , 2 );
addedge( 3 , 1 , 0 );
addedge( 3 , 0 , 8 );
System.out.printf( "%.5f" , minAvgWeight());
}
}
|
Python3
class edge:
def __init__( self , u, w):
self .From = u
self .weight = w
def addedge(u, v, w):
edges[v].append(edge(u, w))
def shortestpath(dp):
for i in range (V + 1 ):
for j in range (V):
dp[i][j] = - 1
dp[ 0 ][ 0 ] = 0
for i in range ( 1 , V + 1 ):
for j in range (V):
for k in range ( len (edges[j])):
if (dp[i - 1 ][edges[j][k].From] ! = - 1 ):
curr_wt = (dp[i - 1 ][edges[j][k].From] +
edges[j][k].weight)
if (dp[i][j] = = - 1 ):
dp[i][j] = curr_wt
else :
dp[i][j] = min (dp[i][j], curr_wt)
def minAvgWeight():
dp = [[ None ] * V for i in range (V + 1 )]
shortestpath(dp)
avg = [ - 1 ] * V
for i in range (V):
if (dp[V][i] ! = - 1 ):
for j in range (V):
if (dp[j][i] ! = - 1 ):
avg[i] = max (avg[i], (dp[V][i] -
dp[j][i]) / (V - j))
result = avg[ 0 ]
for i in range (V):
if (avg[i] ! = - 1 and avg[i] < result):
result = avg[i]
return result
V = 4
edges = [[] for i in range (V)]
addedge( 0 , 1 , 1 )
addedge( 0 , 2 , 10 )
addedge( 1 , 2 , 3 )
addedge( 2 , 3 , 2 )
addedge( 3 , 1 , 0 )
addedge( 3 , 0 , 8 )
print (minAvgWeight())
|
C#
using System;
using System.Collections.Generic;
class GFG{
static int V = 4;
public class Edge
{
public int from , weight;
public Edge( int from ,
int weight)
{
this . from = from ;
this .weight = weight;
}
}
static List<Edge>[] edges =
new List<Edge>[V];
static void addedge( int u,
int v, int w)
{
edges[v].Add( new Edge(u, w));
}
static void shortestpath( int [,] dp)
{
for ( int i = 0; i <= V; i++)
for ( int j = 0; j < V; j++)
dp[i, j] = -1;
dp[0, 0] = 0;
for ( int i = 1; i <= V; i++)
{
for ( int j = 0; j < V; j++)
{
for ( int k = 0;
k < edges[j].Count; k++)
{
if (dp[i - 1,
edges[j][k]. from ] != -1)
{
int curr_wt = dp[i - 1,
edges[j][k]. from ] +
edges[j][k].weight;
if (dp[i, j] == -1)
dp[i, j] = curr_wt;
else
dp[i, j] = Math.Min(dp[i, j],
curr_wt);
}
}
}
}
}
static double minAvgWeight()
{
int [,] dp = new int [V + 1, V];
shortestpath(dp);
double [] avg = new double [V];
for ( int i = 0; i < V; i++)
avg[i] = -1;
for ( int i = 0; i < V; i++)
{
if (dp[V, i] != -1)
{
for ( int j = 0; j < V; j++)
if (dp[j, i] != -1)
avg[i] = Math.Max(avg[i],
(( double ) dp[V, i] -
dp[j, i]) /
(V - j));
}
}
double result = avg[0];
for ( int i = 0; i < V; i++)
if (avg[i] != -1 &&
avg[i] < result)
result = avg[i];
return result;
}
public static void Main(String[] args)
{
for ( int i = 0; i < V; i++)
edges[i] = new List<Edge>();
addedge(0, 1, 1);
addedge(0, 2, 10);
addedge(1, 2, 3);
addedge(2, 3, 2);
addedge(3, 1, 0);
addedge(3, 0, 8);
Console.Write( "{0:F5}" ,
minAvgWeight());
}
}
|
Javascript
<script>
var V = 4;
class Edge
{
constructor(from, weight)
{
this .from = from;
this .weight = weight;
}
}
var edges = Array.from(Array(V), ()=>Array());
function addedge(u, v, w)
{
edges[v].push( new Edge(u, w));
}
function shortestpath(dp)
{
for ( var i = 0; i <= V; i++)
for ( var j = 0; j < V; j++)
dp[i][j] = -1;
dp[0][0] = 0;
for ( var i = 1; i <= V; i++)
{
for ( var j = 0; j < V; j++)
{
for ( var k = 0;
k < edges[j].length; k++)
{
if (dp[i - 1][
edges[j][k].from] != -1)
{
var curr_wt = dp[i - 1][
edges[j][k].from] +
edges[j][k].weight;
if (dp[i][j] == -1)
dp[i][j] = curr_wt;
else
dp[i][j] = Math.min(dp[i][j],
curr_wt);
}
}
}
}
}
function minAvgWeight()
{
var dp = Array.from(Array(V+1), ()=>Array(V).fill(0))
shortestpath(dp);
var avg = Array(V).fill(0);
for ( var i = 0; i < V; i++)
avg[i] = -1;
for ( var i = 0; i < V; i++)
{
if (dp[V][i] != -1)
{
for ( var j = 0; j < V; j++)
if (dp[j][i] != -1)
avg[i] = Math.max(avg[i],
( dp[V][i] -
dp[j][i]) /
(V - j));
}
}
var result = avg[0];
for ( var i = 0; i < V; i++)
if (avg[i] != -1 &&
avg[i] < result)
result = avg[i];
return result;
}
addedge(0, 1, 1);
addedge(0, 2, 10);
addedge(1, 2, 3);
addedge(2, 3, 2);
addedge(3, 1, 0);
addedge(3, 0, 8);
document.write(minAvgWeight().toFixed(5));
</script>
|
Here the graph with no cycle will return value as -1.
Time Complexity : The time complexity of the given program is O(V^3), where V is the number of vertices in the graph. This is because the program uses a nested loop to fill up the dp table, and the size of the dp table is V^2. The outermost loop runs V times, the middle loop runs V times, and the innermost loop can run up to V times in the worst case, giving a total time complexity of O(V^3). The other parts of the program have a lower time complexity and do not contribute significantly to the overall time complexity.
Space Complexity : The space complexity of the given program is O(V^2), where V is the number of vertices in the graph. This is because the program creates a 2D array dp of size (V+1)xV, which requires O(V^2) space. Additionally, the program creates a vector of edges, which takes up O(E) space, where E is the number of edges in the graph. However, in this particular implementation, the number of edges is not directly stored, and it is not clear whether all edges are actually added to the vector. Therefore, the space complexity is mainly determined by the size of the dp array, which is O(V^2).
Please Login to comment...