Karp’s minimum mean (or average) weight cycle algorithm

Given a directed and strongly connected graph with non negative edge weighs. We define 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
karps_mean_value
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 solution of problem 9.2 here for proof that above steps find minimum average weight.

C++

filter_none

edit
close

play_arrow

link
brightness_4
code

// C++ program to find minimum average
// weight of a cycle in connected and
// directed graph.
#include<bits/stdc++.h>
using namespace std;
  
const int V = 4;
  
// a struct to represent edges
struct edge
{
    int from, weight;
};
  
// vector to store edges
vector <edge> edges[V];
  
void addedge(int u,int v,int w)
{
    edges[v].push_back({u, w});
}
  
// calculates the shortest path
void shortestpath(int dp[][V])
{
    // initializing all distances as -1
    for (int i=0; i<=V; i++)
        for (int j=0; j<V; j++)
            dp[i][j] = -1;
  
    // shortest distance from first vertex
    // to in tself consisting of 0 edges
    dp[0][0] = 0;
  
    // filling up the dp table
    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);
                }
            }
        }
    }
}
  
// Returns minimum value of average weight of a
// cycle in graph.
double minAvgWeight()
{
    int dp[V+1][V];
    shortestpath(dp);
  
    // array to store the avg values
    double avg[V];
    for (int i=0; i<V; i++)
        avg[i] = -1;
  
    // Compute average values for all vertices using
    // weights of shortest paths store in dp.
    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));
        }
    }
  
    // Find minimum value in avg[]
    double result = avg[0];
    for (int i=0; i<V; i++)
        if (avg[i] != -1 && avg[i] < result)
            result = avg[i];
  
    return result;
}
  
// Driver function
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;
}

chevron_right


Python3

filter_none

edit
close

play_arrow

link
brightness_4
code

# Python3 program to find minimum 
# average weight of a cycle in 
# connected and directed graph. 
  
# a struct to represent edges 
class edge:
    def __init__(self, u, w):
        self.From = u
        self.weight = w
  
def addedge(u, v, w):
    edges[v].append(edge(u, w))
  
# calculates the shortest path 
def shortestpath(dp):
      
    # initializing all distances as -1
    for i in range(V + 1):
        for j in range(V):
            dp[i][j] = -1
  
    # shortest distance From first vertex 
    # to in tself consisting of 0 edges 
    dp[0][0] = 0
  
    # filling up the dp table
    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)
  
# Returns minimum value of average 
# weight of a cycle in graph. 
def minAvgWeight():
    dp = [[None] * V for i in range(V + 1)]
    shortestpath(dp) 
  
    # array to store the avg values 
    avg = [-1] * V
  
    # Compute average values for all 
    # vertices using weights of 
    # shortest paths store in dp.
    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))
  
    # Find minimum value in avg[] 
    result = avg[0]
    for i in range(V):
        if (avg[i] != -1 and avg[i] < result): 
            result = avg[i] 
  
    return result
  
# Driver Code
V = 4
  
# vector to store edges 
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())
  
# This code is contributed by Pranchalk

chevron_right



Output:

1.66667

Here the graph with no cycle will return value as -1.

Reference:
https://courses.csail.mit.edu/6.046/fall01/handouts/ps9sol.pdf
https://www.hackerearth.com/practice/notes/karp-minimum-mean-weighted-cycle/
Introduction to Algorithms Third Edition page 681 by Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest and Clifford Stein

This article is contributed by Ayush Jha. If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above.



My Personal Notes arrow_drop_up

Improved By : PranchalKatiyar



Article Tags :
Practice Tags :


Be the First to upvote.


Please write to us at contribute@geeksforgeeks.org to report any issue with the above content.