Vind de paden tussen twee gegeven nodes?

stemmen
42

Zeggen dat ik knooppunten in de onderstaande manier aangesloten, hoe kom ik bij het aantal paden die er bestaan ​​tussen bepaalde punten, en het pad informatie?

1,2 //node 1 and 2 are connected
2,3
2,5
4,2
5,11
11,12
6,7
5,6
3,6
6,8
8,10
8,9

Vind de paden 1-7:

Antwoord: 2 paden gevonden en ze zijn

1,2,3,6,7
1,2,5,6,7

Alt-tekst

implementatie gevonden hier is leuk ga ik gebruik maken van dezelfde

Hier is het fragment uit de bovenstaande link in python

# a sample graph
graph = {'A': ['B', 'C','E'],
             'B': ['A','C', 'D'],
             'C': ['D'],
             'D': ['C'],
             'E': ['F','D'],
             'F': ['C']}

class MyQUEUE: # just an implementation of a queue

    def __init__(self):
        self.holder = []

    def enqueue(self,val):
        self.holder.append(val)

    def dequeue(self):
        val = None
        try:
            val = self.holder[0]
            if len(self.holder) == 1:
                self.holder = []
            else:
                self.holder = self.holder[1:]   
        except:
            pass

        return val  

    def IsEmpty(self):
        result = False
        if len(self.holder) == 0:
            result = True
        return result


path_queue = MyQUEUE() # now we make a queue


def BFS(graph,start,end,q):

    temp_path = [start]

    q.enqueue(temp_path)

    while q.IsEmpty() == False:
        tmp_path = q.dequeue()
        last_node = tmp_path[len(tmp_path)-1]
        print tmp_path
        if last_node == end:
            print VALID_PATH : ,tmp_path
        for link_node in graph[last_node]:
            if link_node not in tmp_path:
                #new_path = []
                new_path = tmp_path + [link_node]
                q.enqueue(new_path)

BFS(graph,A,D,path_queue)

-------------results-------------------
['A']
['A', 'B']
['A', 'C']
['A', 'E']
['A', 'B', 'C']
['A', 'B', 'D']
VALID_PATH :  ['A', 'B', 'D']
['A', 'C', 'D']
VALID_PATH :  ['A', 'C', 'D']
['A', 'E', 'F']
['A', 'E', 'D']
VALID_PATH :  ['A', 'E', 'D']
['A', 'B', 'C', 'D']
VALID_PATH :  ['A', 'B', 'C', 'D']
['A', 'E', 'F', 'C']
['A', 'E', 'F', 'C', 'D']
VALID_PATH :  ['A', 'E', 'F', 'C', 'D']
De vraag is gesteld op 03/04/2009 om 12:09
bron van user
In andere talen...                            


8 antwoorden

stemmen
-3

Wat je probeert te doen is in wezen om een pad tussen twee hoekpunten in een (regie?) Grafiek vinden kijk op Dijkstra's algoritme als je kortste pad nodig hebt of schrijf een eenvoudige recursieve functie als u wat paden bestaan.

antwoordde op 03/04/2009 om 12:14
bron van user

stemmen
33

Breedte-first search doorloopt een grafiek en in feite vindt alle paden van een startknooppunt. Meestal heeft BFS niet blijven alle paden, echter. In plaats daarvan werkt een prededecessor functie π om de kortste weg te slaan. U kunt het algoritme eenvoudig wijzigen, zodat π(n)niet alleen op te slaan één voorganger, maar een lijst van mogelijke voorgangers.

Vervolgens worden alle mogelijke paden zijn gecodeerd in deze functie, en met het doorkruisen van n recursief krijg je alle mogelijke combinaties pad.

Een goede pseudocode die deze notatie gebruikt kan worden gevonden in Introduction to Algorithms door Cormen et al. en is vervolgens gebruikt in vele University scripts over het onderwerp. Een Google-zoekopdracht voor “BFS pseudo voorganger π” ontwortelt deze treffer op Stack Exchange .

antwoordde op 03/04/2009 om 12:38
bron van user

stemmen
1

Als u wilt dat alle paden, gebruik recursie.

Via een verbindingslijst voorkeur maakt een functie f () die probeert een actuele lijst van bezochte vertices invullen. Als volgt:

void allPaths(vector<int> previous, int current, int destination)
{
    previous.push_back(current);

    if (current == destination)
        //output all elements of previous, and return

    for (int i = 0; i < neighbors[current].size(); i++)
        allPaths(previous, neighbors[current][i], destination);
}

int main()
{
    //...input
    allPaths(vector<int>(), start, end);
}

Vanwege het feit dat de vector waarde doorgegeven (en dus alle wijzigingen verderop in de recursieve procedure niet permanent), worden alle mogelijke combinaties opgesomd.

U kunt een beetje van de efficiency te krijgen door het passeren van de vorige vector door middel van verwijzing (en dus niet nodig om de vector over en weer te kopiëren), maar dan moet je ervoor zorgen dat dingen popped_back () met de hand.

Nog een ding: als de grafiek cycli, zal dit niet werken. (Ik neem aan dat in dit geval wil je allemaal te vinden eenvoudige paden, toen) Voor het toevoegen van iets in de vorige vector, controleer dan eerst of het is er al in.

Als u wilt dat alle kortste paden, gebruik Konrad suggestie met dit algoritme.

antwoordde op 03/04/2009 om 12:45
bron van user

stemmen
7

Dijkstra's algoritme geldt meer voor gewogen paden en het klinkt als de poster ontbrak om alle wegen te vinden, niet alleen de kortste.

Voor deze toepassing, zou ik het opbouwen van een grafiek (uw aanvraag klinkt alsof het niet zou moeten worden gericht) en gebruik uw favoriete zoekmethode. Het klinkt alsof je alle paden, niet gewoon een gok op de kortste een wilt, dus gebruik een eenvoudige recursieve algoritme van uw keuze.

Het enige probleem is als de grafiek cyclisch kan zijn.

Met de aansluitingen:

  • 1, 2
  • 1, 3
  • 2, 3
  • 2, 4

> 2 - -> 3 -> 1 terwijl op zoek naar een pad uit 1-> 4, kon je een cyclus van 1 hebben.

In dat geval is, dan zou ik een stapel te houden als het doorkruisen van de knooppunten. Hier is een lijst met de stappen voor die grafiek en de resulterende stapel (sorry voor de opmaak - geen tafel optie):

huidige knooppunt (mogelijke volgende nodes minus waar we vandaan kwamen) [stack]

  1. 1 (2, 3) [1]
  2. 2 (3, 4) [1, 2]
  3. 3 (1) [1, 2, 3]
  4. 1 (2, 3) [1, 2, 3, 1] // error - dupliceren nummer op de stack - cyclus gedetecteerd
  5. 3 () [1, 2, 3] // Rug-getrapte knooppunt drie en stopte 1 van de stapel. Niet meer nodes om te verkennen van hier
  6. 2 (4) [1, 2] // back-liep naar knooppunt 2 en stopte 1 van de stapel.
  7. 4 () [1, 2, 4] // Doelknooppunt gevonden - plaat stack een pad. Niet meer nodes om te verkennen van hier
  8. 2 () [1, 2] // back-liep naar knooppunt 2 en stopte 4 van de stapel. Niet meer nodes om te verkennen van hier
  9. 1 (3) [1] // back-liep naar knooppunt 1 en stopte 2 van de stapel.
  10. 3 (2) [1, 3]
  11. 2 (1, 4) [1, 3, 2]
  12. 1 (2, 3) [1, 3, 2, 1] // error - dupliceren nummer op de stack - cyclus gedetecteerd
  13. 2 (4) [1, 3, 2] // Rug-liep naar knooppunt 2 en stopte 1 van de stapel
  14. 4 () [1, 3, 2, 4] Doelknooppunt gevonden - plaat stack een pad. Niet meer nodes om te verkennen van hier
  15. 2 () [1, 3, 2] // back-liep naar knooppunt 2 en stopte 4 van de stapel. Niet meer knooppunten
  16. 3 () [1, 3] // back-liep naar knooppunt 3 en stopte 2 van de stapel. Niet meer knooppunten
  17. 1 () [1] // back-liep naar knooppunt 1 en stopte 3 van de stapel. Niet meer knooppunten
  18. Uitgevoerd met 2 opgenomen paden van [1, 2, 4] en [1, 3, 2, 4]
antwoordde op 03/04/2009 om 12:52
bron van user

stemmen
3

De oorspronkelijke code is een beetje omslachtig en wilt u misschien de collections.deque gebruiken in plaats als u wilt BFS gebruiken om uit te vinden als er een pad bestaat tussen 2 punten op de grafiek. Hier is een snelle oplossing die ik gehackt up:

Let op: deze methode kan oneindig doorgaan als er geen pad tussen de twee knooppunten bestaat. Ik heb niet alle gevallen getest, YMMV.

from collections import deque

# a sample graph
  graph = {'A': ['B', 'C','E'],
           'B': ['A','C', 'D'],
           'C': ['D'],
           'D': ['C'],
           'E': ['F','D'],
           'F': ['C']}

   def BFS(start, end):
    """ Method to determine if a pair of vertices are connected using BFS

    Args:
      start, end: vertices for the traversal.

    Returns:
      [start, v1, v2, ... end]
    """
    path = []
    q = deque()
    q.append(start)
    while len(q):
      tmp_vertex = q.popleft()
      if tmp_vertex not in path:
        path.append(tmp_vertex)

      if tmp_vertex == end:
        return path

      for vertex in graph[tmp_vertex]:
        if vertex not in path:
          q.append(vertex)
antwoordde op 20/07/2009 om 03:22
bron van user

stemmen
22

Voor degenen die niet PYTHON expert, dezelfde code in C ++

//@Author :Ritesh Kumar Gupta
#include <stdio.h>
#include <vector>
#include <algorithm>
#include <vector>
#include <queue>
#include <iostream>
using namespace std;
vector<vector<int> >GRAPH(100);
inline void print_path(vector<int>path)
{
    cout<<"[ ";
    for(int i=0;i<path.size();++i)
    {
        cout<<path[i]<<" ";
    }
    cout<<"]"<<endl;
}
bool isadjacency_node_not_present_in_current_path(int node,vector<int>path)
{
    for(int i=0;i<path.size();++i)
    {
        if(path[i]==node)
        return false;
    }
    return true;
}
int findpaths(int source ,int target ,int totalnode,int totaledge )
{
    vector<int>path;
    path.push_back(source);
    queue<vector<int> >q;
    q.push(path);

    while(!q.empty())
    {
        path=q.front();
        q.pop();

        int last_nodeof_path=path[path.size()-1];
        if(last_nodeof_path==target)
        {
            cout<<"The Required path is:: ";
            print_path(path);
        }
        else
        {
            print_path(path);
        }

        for(int i=0;i<GRAPH[last_nodeof_path].size();++i)
        {
            if(isadjacency_node_not_present_in_current_path(GRAPH[last_nodeof_path][i],path))
            {

                vector<int>new_path(path.begin(),path.end());
                new_path.push_back(GRAPH[last_nodeof_path][i]);
                q.push(new_path);
            }
        }




    }
    return 1;
}
int main()
{
    //freopen("out.txt","w",stdout);
    int T,N,M,u,v,source,target;
    scanf("%d",&T);
    while(T--)
    {
        printf("Enter Total Nodes & Total Edges\n");
        scanf("%d%d",&N,&M);
        for(int i=1;i<=M;++i)
        {
            scanf("%d%d",&u,&v);
            GRAPH[u].push_back(v);
        }
        printf("(Source, target)\n");
        scanf("%d%d",&source,&target);
        findpaths(source,target,N,M);
    }
    //system("pause");
    return 0;
}

/*
Input::
1
6 11
1 2 
1 3
1 5
2 1
2 3
2 4
3 4
4 3
5 6
5 4
6 3
1 4

output:
[ 1 ]
[ 1 2 ]
[ 1 3 ]
[ 1 5 ]
[ 1 2 3 ]
The Required path is:: [ 1 2 4 ]
The Required path is:: [ 1 3 4 ]
[ 1 5 6 ]
The Required path is:: [ 1 5 4 ]
The Required path is:: [ 1 2 3 4 ]
[ 1 2 4 3 ]
[ 1 5 6 3 ]
[ 1 5 4 3 ]
The Required path is:: [ 1 5 6 3 4 ]


*/
antwoordde op 04/06/2012 om 20:17
bron van user

stemmen
2

Gezien de adjacentiematrix:

{0, 1, 3, 4, 0, 0}

{0, 0, 2, 1, 2, 0}

{0, 1, 0, 3, 0, 0}

{0, 1, 1, 0, 0, 1}

{0, 0, 0, 0, 0, 6}

{0, 1, 0, 1, 0, 0}

de volgende Wolfram Mathematica code oplossen van het probleem om de eenvoudige paden tussen twee knopen van een grafiek te vinden. Ik gebruikte eenvoudige recursie, en twee globale var volgen cycli houden en de gewenste output slaan. de code is niet geoptimaliseerd alleen omwille van de duidelijkheid van de code. de "print" moet nuttig zijn om duidelijk te maken hoe het werkt.

cycleQ[l_]:=If[Length[DeleteDuplicates[l]] == Length[l], False, True];
getNode[matrix_, node_]:=Complement[Range[Length[matrix]],Flatten[Position[matrix`node`, 0]]];

builtTree[node_, matrix_]:=Block[{nodes, posAndNodes, root, pos},
    If[{node} != {} && node != endNode ,
        root = node;
        nodes = getNode[matrix, node];
        (*Print["root:",root,"---nodes:",nodes];*)

        AppendTo[lcycle, Flatten[{root, nodes}]];
        If[cycleQ[lcycle] == True,
            lcycle = Most[lcycle]; appendToTree[root, nodes];,
            Print["paths: ", tree, "\n", "root:", root, "---nodes:",nodes];
            appendToTree[root, nodes];

        ];
    ];

appendToTree[root_, nodes_] := Block[{pos, toAdd},
    pos = Flatten[Position[tree[[All, -1]], root]];
    For[i = 1, i <= Length[pos], i++,
        toAdd = Flatten[Thread[{tree[[pos`i`]], {#}}]] & /@ nodes;
        (* check cycles!*)            
        If[cycleQ[#] != True, AppendTo[tree, #]] & /@ toAdd;
    ];
    tree = Delete[tree, {#} & /@ pos];
    builtTree[#, matrix] & /@ Union[tree[[All, -1]]];
    ];
];

de code noemen: initNode = 1; endNode = 6; lcycle = {}; boom = `initNode`; builtTree [initNode, matrix];

paden: '1 root: 1 --- nodes: {2,3,4}

paden: {{1,2}, {1,3}, {1,4}} root: 2 --- nodes: {3,4,5}

paden: {{1,3}, {1,4}, {1,2,3}, {1,2,4}, {1,2,5}} root: 3 --- nodes: {2, 4}

paden: {{1,4}, {1,2,4}, {1,2,5}, {1,3,4}, {1,2,3,4}, {1,3,2, 4}, {1,3,2,5}} root: 4 --- nodes: {2,3,6}

paden: {{1,2,5}, {1,3,2,5}, {1,4,6}, {1,2,4,6}, {1,3,4,6}, { 1,2,3,4,6}, {1,3,2,4,6} {1,4,2,5}, {1,3,4,2,5}, {1,4, 3,2,5}} root: 5 --- nodes: {6}

RESULTATEN: {{1, 4, 6}, {1, 2, 4, 6}, {1, 2, 5, 6}, {1, 3, 4, 6}, {1, 2, 3, 4, 6}, {1, 3, 2, 4, 6}, {1, 3, 2, 5, 6}, {1, 4, 2, 5, 6}, {1, 3, 4, 2, 5, 6}, {1, 4, 3, 2, 5, 6}}

... Helaas kan ik geen beelden uploaden naar de resultaten op een betere manier te tonen :(

http://textanddatamining.blogspot.com

antwoordde op 23/08/2012 om 19:58
bron van user

stemmen
3

In Prolog (specifiek SWI-Prolog)

:- use_module(library(tabling)).

% path(+Graph,?Source,?Target,?Path)
:- table path/4.

path(_,N,N,[N]).
path(G,S,T,[S|Path]) :-
    dif(S,T),
    member(S-I, G), % directed graph
    path(G,I,T,Path).

test:

paths :- Graph =
    [ 1- 2  % node 1 and 2 are connected
    , 2- 3 
    , 2- 5 
    , 4- 2 
    , 5-11
    ,11-12
    , 6- 7 
    , 5- 6 
    , 3- 6 
    , 6- 8 
    , 8-10
    , 8- 9
    ],
    findall(Path, path(Graph,1,7,Path), Paths),
    maplist(writeln, Paths).

?- paths.
[1,2,3,6,7]
[1,2,5,6,7]
true.
antwoordde op 15/09/2016 om 12:02
bron van user

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more