Jak zjistit, zda jsou připojeny dva uzly?

hlasů
13

Obávám se, že by to mohlo být pracuje na NP-úplný problém. Doufám, že někdo mi může dát odpověď na to, zda je či není. A já jsem hledal spíše odpověď než jen ano nebo ne. Rád bych věděl, proč. Pokud můžete říci: „To je v podstatě tento problém‚x‘, která je / není NP-kompletní. (Wikipedia link)“

(No to není domácí)

Existuje způsob, jak určit, zda jsou dva body připojeny na libovolném non-režie grafu. například následující

Well
  |
  |
  A
  |
  +--B--+--C--+--D--+
  |     |     |     |
  |     |     |     |
  E     F     G     H
  |     |     |     |
  |     |     |     |
  +--J--+--K--+--L--+
                    |
                    |
                    M
                    |
                    |
                  House

Body A když M (ne ‚I‘) jsou kontrolní body (jako ventil v zemního plynu potrubí), které mohou být buď otevřené nebo uzavřené. Na ‚+‘ s jsou uzly (jako je trubka T je), a myslím, že dobře a dům jsou také uzly stejně.

Chtěl bych vědět, jestli jsem zavřel libovolný řídicí bod (například C), zda je dobře a dům je stále připojen (jiné kontrolní body mohou být rovněž uzavřeny). Například, je-li B, K a D jsou zavřené, máme před sebou ještě cestu přes AEJFCGLM a zavírání C odpojí studna a dům. Samozřejmě; když jen D byl uzavřen, zavírání pouze C neodpojí dům.

Dalším způsobem, jak to je C most / řezná hrana / šíje?

Mohu léčit každý kontrolní bod jako hmotnost na grafu (buď 0 pro otevřené nebo 1 pro uzavřený); a pak najít nejkratší cestu mezi Well a domu (výsledek> = 1 by znamenalo, že by byly odpojeny. Je tu různé způsoby, jak mohu zkrat algoritmus pro hledání nejkratší cesty příliš (např vyřadit cestu, jakmile se dostane 1, zastavte vyhledávání jakmile budeme mít libovolnou cestu, která spojuje studna a dům, atd.) a samozřejmě také mohu dát do nějaké umělé hranice, kolik chmele zkontrolovat před udělením.

Někdo musel klasifikovala tento druh problému dříve, já jen chybí název.

Položena 09/12/2008 v 22:41
zdroj uživatelem
V jiných jazycích...                            


11 odpovědí

hlasů
2

ne NP-úplný, vyřešit pomocí dobře známého řešení - Dijkstrův algoritmus

Odpovězeno 09/12/2008 v 22:43
zdroj uživatelem

hlasů
6

Viz http://en.wikipedia.org/wiki/Dijkstra%27s_algorithm , vaše one stop shop pro všechny problémy spojené grafů. Věřím, že váš problém je v tom, řešitelná kvadratické čase.

Odpovězeno 09/12/2008 v 22:45
zdroj uživatelem

hlasů
2

Zdá se mi, jako byste se na řešení, ale je to možné, jsem nepochopil problém. Pokud tak učiníte, jako byste říci, a dát uzavřené hrany 1, jak hmotnosti, stačí aplikovat Dijkstrova algoritmu, http://en.wikipedia.org/wiki/Dijkstra%27s_algorithm . To by mělo vyřešit váš problém v O (E * lg (V))

Odpovězeno 09/12/2008 v 22:49
zdroj uživatelem

hlasů
3

Problém najít nejkratší cestu není NP-úplné. Říká se tomu nejkratší cestu Problem (původně dost), a tam jsou algoritmy pro řešit mnoho různých variant ní.

Problém určování, zda jsou spojeny dva uzly není NP-úplný jeden. Můžete použít první hledání hloubky začíná na obou uzlu zjistit, zda je připojen do uzlu.

Odpovězeno 09/12/2008 v 22:51
zdroj uživatelem

hlasů
31

Váš popis nasvědčuje tomu, že jste právě zájem o to, zda jsou připojeny dva uzly, nemůže najít nejkratší cestu.

Zjištění, pokud jsou připojeny dva uzly je poměrně snadné:

Create two sets of nodes:  toDoSet and doneSet
Add the source node to the toDoSet 
while (toDoSet is not empty) {
  Remove the first element from toDoList
  Add it to doneList
  foreach (node reachable from the removed node) {
    if (the node equals the destination node) {
       return success
    }
    if (the node is not in doneSet) {
       add it to toDoSet 
    }
  }
}

return failure.

Pokud použijete hash tabulky nebo něco podobného pro toDoSet a doneSet, věřím, že se jedná o lineární algoritmus.

Všimněte si, že tento algoritmus je v podstatě známka část mark-and-sweep garbage collection.

Odpovězeno 09/12/2008 v 22:52
zdroj uživatelem

hlasů
5

Nepotřebujete Dijkstrova algoritmus pro tento problém, protože používá hromadu, která není potřebná a zavádí faktor log (N) ke svému složitosti. To je právě prohledávání do šířky - neobsahují uzavřené hrany jsou hrany.

Odpovězeno 09/12/2008 v 23:08
zdroj uživatelem

hlasů
2

Za předpokladu, že máte matice sousednosti:

bool[,] adj = new bool[n, n];

V případě, bool [i, j] = true, pokud je otevřený cesta mezi i a j a bool [i, j] = false.

public bool pathExists(int[,] adj, int start, int end)
{
  List<int> visited = new List<int>();
  List<int> inprocess = new List<int>();
  inprocess.Add(start);

  while(inprocess.Count > 0)
  {
    int cur = inprocess[0];
    inprocess.RemoveAt(0);
    if(cur == end)
      return true;
    if(visited.Contains(cur))
      continue;
    visited.Add(cur);
    for(int i = 0; i < adj.Length; i++)
      if(adj[cur, i] && !visited.Contains(i) && !inprocess.Contains(i))
        inprocess.Add(i);
  }
  return false;
}

Zde je rekurzivní verzi algoritmu výše (napsaný v Ruby):

def connected? from, to, edges
  return true if from == to
  return true if edges.include?([from, to])
  return true if edges.include?([to, from])

  adjacent = edges.find_all { |e| e.include? from }
                  .flatten
                  .reject { |e| e == from }

  return adjacent.map do |a|
    connected? a, to, edges.reject { |e| e.include? from }
  end.any?
end
Odpovězeno 09/12/2008 v 23:23
zdroj uživatelem

hlasů
0

Dijkstra to je zbytečná !! Stačí použít prohledávání do šířky od A k hledání uzlu, který chcete dosáhnout. Pokud nemůžete najít, to není připojen. Složitost je O (nm) pro každý vyhledávání, který je menší než Dijkstra.

Poněkud související je / problém max-min toku řezaného. Najděte si to, to by mohlo být důležité pro váš problém.

Odpovězeno 12/12/2008 v 15:11
zdroj uživatelem

hlasů
0

Pokud vše, co potřebujete, je zjistit, zda jsou 2 uzly spojeny můžete použít sady místo, které je rychlejší než grafových algoritmů.

  1. Rozdělit celý graf na hranách. Přidat každou hranu k sadě.
  2. V následující iteraci, kreslit okraje mezi 2 vnějšími uzly hrany provedené v kroku 2. To znamená, že přidání nových uzlů (s jejich příslušnými sadami) k nastavení původní okraj byl od. (V podstatě nastavit sloučení)
  3. Opakujte 2 až do 2 uzly, které hledáte, jsou ve stejné sadě. Budete také muset provést kontrolu po kroku 1 (jen v případě, že 2 uzly jsou přilehlé).

Zpočátku své uzly budou každý ve svém setu,

o   o1   o   o   o   o   o   o2
 \ /     \ /     \ /     \ /
 o o     o o     o o     o o
   \     /         \     /
   o o o o         o o o o 
      \               /
       o o1 o o o o o o2

Vzhledem k tomu, algoritmus postupuje a slučuje sady, to poměrně polovinu vstup.

Ve výše uvedeném příkladu jsem se snaží zjistit, zda došlo k cesta mezi O1 a O2. Tuto cestu jsem našel pouze na konci po sloučení všech hran. Některé grafy mohou mít jednotlivé složky (odpojeno), což znamená, že nebudete moci mít jednu sadu na konci. V takovém případě můžete použít tento algoritmus pro testování sounáležitosti a dokonce spočítat počet prvků v grafu. Počet komponent je počet sad jste schopni získat, když algoritmus skončí.

Možným graf (pro stromu výše):

o-o1-o-o-o2
  |    |
  o    o
       |
       o
Odpovězeno 17/12/2011 v 04:14
zdroj uživatelem

hlasů
-1

Jakékoli graf algoritmus nejkratší cesta bude zbytečná, pokud vše, co potřebujete, je zjistit, zda je uzel připojen k druhému. Dobrý Java knihovna, která dosáhne, že je JGraphT . Je to použití je velmi jednoduché, zde je příklad celé číslo grafu:

public void loadGraph() {
    // first we create a new undirected graph of Integers
    UndirectedGraph<Integer, DefaultEdge> graph = new SimpleGraph<>(DefaultEdge.class);

    // then we add some nodes
    graph.addVertex(1);
    graph.addVertex(2);
    graph.addVertex(3);
    graph.addVertex(4);
    graph.addVertex(5);
    graph.addVertex(6);
    graph.addVertex(7);
    graph.addVertex(8);
    graph.addVertex(9);
    graph.addVertex(10);
    graph.addVertex(11);
    graph.addVertex(12);
    graph.addVertex(13);
    graph.addVertex(14);
    graph.addVertex(15);
    graph.addVertex(16);

    // then we connect the nodes
    graph.addEdge(1, 2);
    graph.addEdge(2, 3);
    graph.addEdge(3, 4);
    graph.addEdge(3, 5);
    graph.addEdge(5, 6);
    graph.addEdge(6, 7);
    graph.addEdge(7, 8);
    graph.addEdge(8, 9);
    graph.addEdge(9, 10);
    graph.addEdge(10, 11);
    graph.addEdge(11, 12);
    graph.addEdge(13, 14);
    graph.addEdge(14, 15);
    graph.addEdge(15, 16);

    // finally we use ConnectivityInspector to check nodes connectivity
    ConnectivityInspector<Integer, DefaultEdge> inspector = new ConnectivityInspector<>(graph);

    debug(inspector, 1, 2);
    debug(inspector, 1, 4);
    debug(inspector, 1, 3);
    debug(inspector, 1, 12);
    debug(inspector, 16, 5);
}

private void debug(ConnectivityInspector<Integer, DefaultEdge> inspector, Integer n1, Integer n2) {
    System.out.println(String.format("are [%s] and [%s] connected? [%s]", n1, n2, inspector.pathExists(n1, n2)));
}

Tento lib také nabízí všechny nejkratší cesty algoritmy stejně.

Odpovězeno 14/11/2016 v 06:34
zdroj uživatelem

hlasů
0

Vidím, že jste dostali odpověď, že to rozhodně není NP-kompletní, a to je velmi stará otázka stejně.

Nicméně, budu jen navrhnout jiný přístup k dívat se na problém. Dalo by se použít nesouvislý sady pro toto. Ve většině případů je pro daný scénář, tento přístup bude mít za následek lepší čas, než dělá graf traversal (To zahrnuje konstantní čas pro velký kus testů). Nicméně, budování graf může trvat dobré množství času, pokud se používá svaz podle hodnosti nebo cestou komprese.

Můžete si přečíst o datovou strukturu zde .

Odpovězeno 03/09/2018 v 13:36
zdroj uživatelem

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