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

11 Jul, 2022
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++
Java
Python3
C#
Javascript
// 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 edgesstruct edge{    int from, weight;}; // vector to store edgesvector <edge> edges[V]; void addedge(int u,int v,int w){    edges[v].push_back({u, w});} // calculates the shortest pathvoid 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 itself 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 functionint 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 program to find minimum average// weight of a cycle in connected and// directed graph.import java.io.*;import java.util.*; class GFG{static int V = 4; // a struct to represent edgesstatic class Edge{    int from, weight;     Edge(int from, int weight)    {        this.from = from;        this.weight = weight;    }} // vector to store edges//@SuppressWarnings("unchecked")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));} // calculates the shortest pathstatic void shortestpath(int[][] dp){    // 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 itself 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].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);                }            }        }    }} // Returns minimum value of average weight// of a cycle in graph.static double minAvgWeight(){    int[][] dp = new int[V + 1][V];    shortestpath(dp);     // array to store the avg values    double[] avg = new double[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] = Math.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 Codepublic 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());}} // This code is contributed by// sanjeev2552
# Python3 program to find minimum# average weight of a cycle in# connected and directed graph. # a struct to represent edgesclass 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 pathdef 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 itself 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 CodeV = 4 # vector to store edgesedges = [[] 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
// C# program to find minimum// average weight of a cycle// in connected and directed graph.using System;using System.Collections.Generic;class GFG{   static int V = 4; // a struct to represent// edgespublic class Edge{  public int from, weight;  public Edge(int from,              int weight)  {    this.from = from;    this.weight = weight;  }} // vector to store edges static List<Edge>[] edges =            new List<Edge>[V];  static void addedge(int u,                    int v, int w){  edges[v].Add(new Edge(u, w));} // calculates the shortest pathstatic void shortestpath(int[,] dp){  // 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 itself  // 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].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);        }      }    }  }} // Returns minimum value of// average weight of a cycle// in graph.static double minAvgWeight(){  int[,] dp = new int[V + 1, V];  shortestpath(dp);   // array to store the  // avg values  double[] avg = new double[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] = Math.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 Codepublic 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());}} // This code is contributed by Princi Singh
<script> // JavaScript program to find minimum// average weight of a cycle// in connected and directed graph.   var V = 4; // a struct to represent// edgesclass Edge{    constructor(from, weight)    {        this.from = from;        this.weight = weight;    }} // vector to store edges var edges = Array.from(Array(V), ()=>Array()); function addedge(u, v, w){  edges[v].push(new Edge(u, w));} // calculates the shortest pathfunction shortestpath(dp){  // initializing all distances  // as -1  for (var i = 0; i <= V; i++)    for (var j = 0; j < V; j++)      dp[i][j] = -1;   // shortest distance from  // first vertex to in itself  // consisting of 0 edges  dp[0][0] = 0;   // filling up the dp table  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);        }      }    }  }} // Returns minimum value of// average weight of a cycle// in graph.function minAvgWeight(){  var dp = Array.from(Array(V+1), ()=>Array(V).fill(0))  shortestpath(dp);   // array to store the  // avg values  var avg = Array(V).fill(0);     for (var i = 0; i < V; i++)    avg[i] = -1;   // Compute average values for  // all vertices using weights  // of shortest paths store in dp.  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));    }  }   // Find minimum value in avg[]  var result = avg[0];     for (var i = 0; i < V; i++)    if (avg[i] != -1 &&        avg[i] < result)      result = avg[i];   return result;} // Driver Codeaddedge(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>
1.66667
Here the graph with no cycle will return value as -1.
This article is contributed by Ayush Jha. If you like GeeksforGeeks and would like to contribute, you can also write an article using write.geeksforgeeks.org or mail your article to review-team@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.
PranchalKatiyar
sanjeev2552
princi singh
itsok
sumitgumber28
kothavvsaakash
hardikkoriintern
graph-cycle
Shortest Path
Graph
Graph
Shortest Path
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.