Алгоритм удаления наименьшего количества ребер для увеличения длины кратчайшего пути в невзвешенном неориентированном графе

Учитывая матрицу смежности для невзвешенного неориентированного графа, существует ли эффективный способ (полиномиальный алгоритм) расширить / увеличить длину кратчайшего пути между любыми заданными двумя узлами s и t?

Пример:

В приведенном ниже примере есть 5 различных «кратчайших путей» от вершины s = 1 до вершины t = 5, каждый из которых имеет длину 3. Я хочу удалить наименьшее количество ребер, чтобы длина кратчайшего пути была равна 4 или более. (Отключение графика - нормально.)

Матрица смежности (расширена для исправления примера):

 0 1 0 0 0 1 1 1 0 1 0 
 1 0 1 1 0 0 0 0 0 0 0  
 0 1 0 0 1 0 0 0 0 0 1 
 0 1 0 0 1 1 0 0 0 0 0  
 0 0 1 1 0 1 0 0 0 0 0 
 1 0 0 1 1 0 0 0 1 0 0 
 1 0 0 0 0 0 0 0 1 0 0 
 1 0 0 0 0 0 0 0 1 0 0 
 0 0 0 0 0 1 1 1 0 0 0
 1 0 0 0 0 0 0 0 0 0 1
 0 0 1 0 0 0 0 0 0 1 0 

представляющий этот график:

Модифицированный график (AKE)

Минимальные затраты на увеличение длины кратчайшего пути с 3 до 4 - это удаление двух кромок (1,2) и (5,9).

Цель:

Можете ли вы дать какие-либо идеи для общего алгоритма, который находит набор ребер, которые необходимо удалить в общем случае?


Исправление: Как отмечалось в моих комментариях, этот пример не является полным. Добавив еще две вершины 10 и 11 (показаны красным), пример спасен.


person Alireza Farahani    schedule 24.01.2013    source источник
comment
Что ты пробовал? Пожалуйста, опубликуйте матрицу смежности для описываемого вами примера (избавляет нас от необходимости думать о таком).   -  person Assad Ebrahim    schedule 24.01.2013
comment
@AKE Я редактировал вопрос.   -  person Alireza Farahani    schedule 24.01.2013
comment
Какие вершины - это s и t?   -  person Assad Ebrahim    schedule 25.01.2013
comment
@ake 1 - источник, а 5 - сток   -  person Alireza Farahani    schedule 25.01.2013
comment
Затем, если вы удалите (1,2) и (5,9), вы отключите график. Итак, между 1 и 5 НЕТ пути, так как же получить путь длиной 4?   -  person Assad Ebrahim    schedule 25.01.2013
comment
@AKE Я упомянул в вопросе. основная цель - увеличить длину кратчайшего пути за счет удаления минимального количества ребер. (связность графа не имеет значения)   -  person Alireza Farahani    schedule 25.01.2013
comment
другими словами, если кратчайший путь между s и t равен 5, мы должны удалить минимальное количество ребер, чтобы больше не существовало пути длиной 5 между s и t.   -  person Alireza Farahani    schedule 25.01.2013
comment
Я понимаю вопрос. Однако ваш пример и ваши утверждения по этому поводу неверны. Предлагаю вам привести хороший рабочий пример. Это показывает, что вы сами приложили определенные усилия.   -  person Assad Ebrahim    schedule 25.01.2013
comment
Я исправил для вас ваш пример - обратите внимание на дополнительные узлы, выделенные красным, а также таблицу смежности. Что вы пробовали на этом рабочем примере?   -  person Assad Ebrahim    schedule 27.01.2013
comment
@AKE: Я решил вопрос с помощью теоремы о максимальном потоке и минимальном сокращении. ответ - края минимального разреза   -  person Alireza Farahani    schedule 27.01.2013
comment
Отличная работа. Почему бы не опубликовать свой ответ? Также: это не может быть весь минимальный разрез, так как в противном случае граф будет отключен и нет пути между источником и приемником. Предположительно вы имеете в виду часть разреза?   -  person Assad Ebrahim    schedule 27.01.2013


Ответы (2)


Входные данные: G = (V, E), вершины s, t и положительное целое число d.

Вопрос: Минимизируйте количество ребер, необходимых для удаления, так, чтобы dist (s, t)> = d.

Эта проблема NP-трудна для d> 3 и полиномиально разрешима для других значений d.

Проблема заключается в том, что FPT параметризован на расстоянии d и количестве ребер, которые вам разрешено удалять, k: Алгоритм следующий: найдите (s, t) -путь длиной не более d и разветвляйтесь на d ребрах, до которых вы можно удалить. Это приводит к алгоритму, который выполняется за время O (d ^ k * n ^ 2).

Он является пара-NP-полным (соответственно W [1] -жестким), если параметризован просто d (соответственно просто k).

Ссылка: Пути ограниченной длины и их разрезы: параметризованная сложность и алгоритмы, Головач П.А. и Тиликос, Д.М., Дискретная оптимизация, том 8, номер 1, страницы 72-86, 2011 год, издательство Elsevier.

person Pål GD    schedule 29.01.2013
comment
Не могли бы вы дать ссылку на ваш источник по этому поводу? - person templatetypedef; 30.01.2013
comment
это p вопрос! Я решил это, найдя максимальный поток для данного графа, а затем найдя минимально обрезанные ребра с помощью BFS. Я скоро отправлю свой ответ. - person Alireza Farahani; 30.01.2013
comment
@templatetypedef Добавлена ​​ссылка, они называют проблему BEUC, Bounded Edge Undirected (s, t) -cut. - person Pål GD; 30.01.2013
comment
@alireza Проблема полиномиально разрешима тогда и только тогда, когда расстояние и количество ребер, которые вам разрешено удалять, считаются постоянными (при условии, что P! = NP). - person Pål GD; 30.01.2013

Я решил это с помощью подхода, упомянутого в третьем комментарии ответа «Pål GD». Вот код этого java. Надеюсь, вы найдете это полезным!

// BFS to find the depth of every node (from source node)
// graph is the adjacency matrix.
// elements of row zero and column zero are all useless. this program
// works with indices >=1 
private int[][] BFS (int[][] graph, int source, boolean SPedges){
    int[][] temp = null;

    // nodes is number of graph nodes. (nodes == graph.length - 1)
    if (SPedges){
        temp = new int[nodes + 1][nodes + 1];
    }
    else{
        depth[source] = 0;
    }
    LinkedList<Integer> Q = new LinkedList<Integer>();
    Q.clear();
    visited[source] = true;
    Q.addFirst(source);
    while (!Q.isEmpty()){
        int u = Q.removeLast();
        for (int k = 1; k <= nodes; k++){
            if (!SPedges){
                // checking if there's a edge between node u and other nodes
                if (graph[u][k] == 1 && visited[k] == false){
                    visited[k] = true;
                    depth[k] = depth[u] + 1;
                    Q.addFirst(k);
                }
            }
            else{
                if (graph[u][k] == 1 && depth[k] == depth[u] - 1){
                    Q.addFirst(k);
                    temp[k][u] = 1;
                }
            }
        }   
    }
    return temp;
}

// fills the edges of shortest path graph in flow 
private ArrayList<Edge> maxFlow(int[][] spg, int source, int sink){ 
    int u = source;
    ArrayList<Integer> path = new ArrayList<Integer> (depth[sink]);
    path.add(source);
    Arrays.fill(visited, false);
    visited[source] = true;
    for (int i = 1; i <= nodes + 1; i++){
        if (i == nodes + 1){
            if (u == source)
                break;
            u = path.get(path.size() - 2);
            i = path.remove(path.size() - 1);
        }
        else if(spg[u][i] == 1 && visited[i] == false){
            visited[i] = true;
            path.add(i);
            if (i == sink){
                for(int k = 0; k < path.size() - 1; k++){
                    spg[path.get(k)][path.get(k+1)] = 0;
                    spg[path.get(k+1)][path.get(k)] = 1;
                }
                i = 0;
                u = source;
                path.clear();
                path.add(u);
                Arrays.fill(visited, false);
            }
            else{
                u = i;
                i = 0;
            }
        }
    }

    LinkedList<Integer> Q = new LinkedList<Integer>();
    Q.clear();

    Arrays.fill(visited, false);

    visited[source] = true;
    Q.addFirst(source);
    while (!Q.isEmpty()){
        u = Q.removeLast();
        for (int k = 1; k <= nodes; k++){
            if (spg[u][k] == 1 && visited[k] == false){
                visited[k] = true;
                Q.addFirst(k);
            }   
        }
    }
    ArrayList<Edge> edges = new ArrayList<Edge>();
    for (int i = 1; i <= nodes; i++){
        for (int j = 1; j <= nodes; j++){
            if ((spg[i][j] == 1) && (visited[i] ^ visited[j])){
                edges.add(new Edge(i, j));
            }
        }
    }

    return edges;
}

public void Solv(){
    // adjacency matrix as g. represents the graph.
    // first we find depth of each node corresponding to source node by a BFS from source
    BFS(g, s, false);

    // shortest path length from source to sink (node t)
    SPL = depth[t];

    // shortest path graph
    // it's a subgraph of main graph consisting only edges that are in a shortest path
    // between s and t
    spg = BFS(g, t, true);

    // lastly we find edges of a min cut in shortest paths graph
    // and store them in "edges"
    edges = maxFlow(spg, s, t);
}    

class Edge{
    private int begin, end;
    public Edge(int begin, int end){
        this.begin = begin;
        this.end = end;
    }
    @Override
    public String toString() {
        return new String(String.valueOf(begin) + " " + String.valueOf(end));
    }
}
person Alireza Farahani    schedule 29.05.2014