Find the minimum weighted path in a graph with additional conditions

Viewed 319

I have a problem as below and I am really stuck with it as it run with more than the time I desired (about 1 second). I really want your help to build up a more efficient algorithms than mine

Given an undirected graph G = (V, E) with two parameter of weights w1 and w2 for each edges. This graph has N vertices and M edges. A K-Elementary path S is a sub-graph of G which must be an elementary graph and it does have exactly K edges.

Find a K-elementary path S with the sum of w1 of all edges as minimum value and the sum of w2 of all edges of S must be smaller than a given value Q. If it does not exist any path satisfied, print out the value -1

Input:

The first line with four values N, M, K, Q (2 <= N, K <= 50, 1 <= M <= 2*N, 1 <= Q <= 10^9)

The next M lines show the edges of the graph: V1 V2 W1 W2 (1 <= V1, V2 <= N, 1 <= W1 <= 10^4, 1 <= W2 <= 10^4)

Output: One integer to show the minimum weight of the k-elementary graph found. -1 if non-exists

Sample test case:

Input:

5 7 3 6
1 2 1 2
1 4 2 2
1 5 3 6
2 3 3 2
2 4 4 4
3 4 5 1
4 5 4 7

Output:

6

First of all, I want to quote the definition of an elementary path.

In short, for this problem, we need to find an k-elementary path S such that the weight to w1 is minimum, the sum of all edges to w2 is less than or equal to Q and it does have exactly K edges.

I do have a Backtracking approach, in which I tried to build up all the graph satisfying the second condition (w2) and then find the minimum of the first condition (w1) but, as you have known, the time complexity is quite high. However, I find it hard to convert it to dynamic programming or any other methods to reduce to time complexity. I do add some Branch-bound condition but it is still slow.

Below is my source code which you can refer but I do not think it is useful

#include <bits/stdc++.h>
using namespace std;
#define N 51
#define INF 1e9
int n, m, K, Q;
bool appear[N];
int W1[N][N];
int W2[N][N];
int currentSum1 = 0;
int currentSum2 = 0;
int source = 0;
int res = INF;
int Log[N];
int minElement = INF;
bool check(int k, int v)
{
    return !appear[v] && W1[Log[k - 1]][v] != 0 && W2[Log[k - 1]][v] != 0;
}
void solution()
{
    if(currentSum1 != 0 && currentSum1 < res)
    {
        res = currentSum1;
        // for(int i = 0; i <= K; i++)
        //     cout << Log[i] << " ";
        // cout << endl;
    }
}
void solve(int k)
{
    for(int v = 1; v <= n; v++)
    {
        if(check(k, v) && currentSum2 + W2[source][v] <= Q && currentSum1 + (K - k) * minElement <= res) //Branch-bound condition
        {
            Log[k] = v;
            currentSum2 += W2[Log[k - 1]][v];
            currentSum1 += W1[Log[k - 1]][v];
            appear[v] = true;
            if(k == K)
                solution();
            else
                solve(k + 1);
            currentSum1 -= W1[Log[k - 1]][v];
            currentSum2 -= W2[Log[k - 1]][v];
            appear[v] = false;
        }
    }
}
int main()
{
    fast;
    // freopen("data.txt", "r", stdin);
    cin >> n >> m >> K >> Q;
    for(int i = 0; i < m; i++)
    {
        int x, y, w1, w2;
        cin >> x >> y >> w1 >> w2;
        minElement = min(minElement, w1);
        W1[x][y] = w1;
        W1[y][x] = w1;
        W2[x][y] = w2;
        W2[y][x] = w2;
    }
    for(int v = 1; v <= n; v++)
    {
        source = v;
        currentSum2 = 0;
        currentSum1 = 0;
        Log[0] = v;
        for(int i = 1; i <= n; i++)
            appear[i] = false;
        appear[source] = true;
        solve(1);
    }
    if(res != INF)
        cout << res << endl;
    else 
        cout << -1 << endl;
}
1 Answers

Firstly, finding a resource constrained shortest path is NPHard. Most approaches to this problem employ a labelling scheme, which is a specialization of dynamic programming. You could use available libraries to accomplish this. See here for a boost implementation. This implementation will help you find (possibly) a non-elementary path from s to t as long all of the w_2 weights are positive. If the weights w_2's are negative, then it is possible that with negative w_1 weights and positive Q, the problem is unbounded.

Now, coming to the need for a k-elementary shortest path, as far as I know, there is no off-the shelf algorithm that could help accomplish this. First, forget about k. Finding an elementary shortest path subject to additional resource constraints can be done using the labelling schemed presented in the papers referred to in the boost link above. In this case, the state space of the dynamic program should increase to allow for the storage of the indicator vector of all previously visited nodes in the path. This make the problem much harder to solve as compared to the basic resource constrained shortest path problem.

Now, getting to your need of a k-elementary shortest path, one would have to embed the above scheme of finding an elementary shortest path recursively inside another function that keeps checking whether the elementary path returned has k edges or not. If it does have k edges, then you are done. If not, you would have to somehow place restrictions on the algorithm to prevent this particular path. That can be accomplished by using prelabels. As far as I know, this was first done in this work.

Good luck, but this problem is doubly/triply difficult (because of possible need for multiple iterations). You should refer to the work mentioned in the boost link and subsequent papers in this area to understand the state-of-the-art. I suspect the state-of-the-art to not be able to solve problems beyond 10-15 nodes.

Related