Bir Grafikteki En Uzun Çevrim


18

Yönlendirilmiş bir grafik verildiğinde, en uzun döngüyü elde edin.

kurallar

  • Herhangi bir makul giriş formatına izin verilir (örn. Kenar listesi, bağlantı matrisi).
  • Etiketler önemli değildir, bu nedenle girdi içerisinde verilmeyen ek bilgiler içermedikleri sürece ihtiyacınız olan ve / veya arzu ettiğiniz etiketler için herhangi bir kısıtlama uygulayabilirsiniz (örneğin, döngüdeki düğümlerin tamsayılarla ve diğer düğümler alfabetik dizelerle etiketlenmiştir).
  • Bir döngü, döngünün başlangıcı ve bitişi olan ( [1, 2, 3, 1]bir döngüdür, ancak [1, 2, 3, 2, 1]değildir) düğüm dışındaki tüm düğümlerin bağlı olduğu bir düğüm dizisidir .
  • Grafik döngüsel değilse, en uzun döngü 0 uzunluğuna sahiptir ve bu nedenle boş bir çıktı vermelidir (örneğin boş liste, hiç çıktı yok).
  • Döngüdeki düğüm listesinin sonunda ilk düğümü tekrarlamak isteğe bağlıdır ( [1, 2, 3, 1]ve [1, 2, 3]aynı döngüyü gösterir).
  • Aynı uzunlukta birden çok döngü varsa, bunlardan herhangi biri veya tamamı çıktılanabilir.
  • Yerleşiklere izin verilir, ancak çözümünüz bir tane kullanıyorsa, önemsizleştirici yerleşikleri (örneğin, tüm döngüleri veren bir yerleşik) kullanmayan alternatif bir çözüm eklemeniz önerilir. Ancak, alternatif çözüm puanınıza hiç sayılmaz, bu yüzden tamamen isteğe bağlıdır.

Test Durumları

Bu test durumlarında, girdi bir kenar listesi olarak verilir (burada birinci eleman kaynak düğümdür ve ikinci eleman hedef düğümdür) ve çıkış, ilk / son düğümü tekrarlamadan düğümlerin bir listesidir.

[(0, 0), (0, 1)] -> [0]
[(0, 1), (1, 2)] -> []
[(0, 1), (1, 0)] -> [0, 1]
[(0, 1), (1, 2), (1, 3), (2, 4), (4, 5), (5, 1)] -> [1, 2, 4, 5]
[(0, 1), (0, 2), (1, 3), (2, 4), (3, 0), (4, 6), (6, 8), (8, 0)] -> [0, 2, 4, 6, 8]
[(0, 0), (0, 8), (0, 2), (0, 3), (0, 9), (1, 0), (1, 1), (1, 6), (1, 7), (1, 8), (1, 9), (2, 1), (2, 3), (2, 4), (2, 5), (3, 8), (3, 1), (3, 6), (3, 7), (4, 1), (4, 3), (4, 4), (4, 5), (4, 6), (4, 8), (5, 0), (5, 8), (5, 4), (6, 0), (6, 1), (6, 2), (6, 3), (6, 4), (6, 5), (6, 6), (6, 7), (6, 9), (7, 0), (7, 1), (7, 2), (7, 3), (7, 4), (7, 5), (7, 8), (7, 9), (8, 0), (8, 1), (8, 2), (8, 5), (8, 9), (9, 1), (9, 2), (9, 3), (9, 4), (9, 5), (9, 6)] -> [0, 9, 6, 7, 8, 2, 5, 4, 3, 1]
[(0, 0), (0, 2), (0, 4), (0, 5), (0, 7), (0, 9), (0, 11), (1, 2), (1, 4), (1, 5), (1, 8), (1, 9), (1, 10), (2, 0), (2, 1), (2, 3), (2, 4), (2, 5), (2, 6), (3, 0), (3, 1), (3, 5), (3, 6), (3, 7), (3, 8), (3, 9), (3, 11), (4, 1), (4, 3), (4, 7), (4, 8), (4, 9), (4, 10), (4, 11), (5, 0), (5, 4), (5, 6), (5, 7), (5, 8), (5, 11), (6, 0), (6, 8), (6, 10), (6, 3), (6, 9), (7, 8), (7, 9), (7, 2), (7, 4), (7, 5), (8, 8), (8, 9), (8, 2), (8, 4), (8, 7), (9, 0), (9, 1), (9, 2), (9, 3), (9, 6), (9, 10), (9, 11), (10, 8), (10, 3), (10, 5), (10, 6), (11, 2), (11, 4), (11, 5), (11, 9), (11, 10), (11, 11)] -> [0, 11, 10, 6, 9, 3, 8, 7, 5, 4, 1, 2]

Tüm örneklerinizde, çıktınız en küçük dizine sahip düğümle başlar. Bu bir gereklilik mi?
Dada

@Dada Hayır, bu sadece test senaryolarıyla bir tesadüf. Çıkış, döngüdeki ilk düğümle başlamalı (ve isteğe bağlı olarak sona ermelidir).
Mego

Bitiş noktası olan veya olmayan bir format seçmelisiniz ve meydan okumaya hiçbir şey eklemez.
Sihirli Ahtapot Urn

5
@carusocomputing Katılıyorum. Son düğüm, bırakılırsa örtüktür (ilk düğümle aynı olduğundan). İlk düğümü tekrar edip etmeme seçimine izin vermek golfte daha fazla özgürlük sağlar.
Mego

Yanıtlar:


4

Mathematica, 80 58 bayt

JungHwan Min sayesinde 22 bayt kurtardı

(FindCycle[#,∞,All]/.{}->{Cases[#,v_v_]})[[-1,;;,1]]&

üç baytlık özel kullanım karakteri U+F3D5temsil eden\[DirectedEdge] . İlk argümanlı saf fonksiyonun #yönlendirilmiş kenarların bir listesi olması bekleniyor. AllUzunluk döngülerini en fazla Infinityinç cinsinden bulur Graph@#, ardından boş listeyi otomatik döngüler listesiyle değiştirir. Döngüler kenar listeleri olarak temsil edilir ve uzunluğa göre sıralanır, bu nedenle son döngüyü alırız, ardından tüm kenarlarından ilk çıktıyı alırız, böylece belirtilen çıktı biçimindeki köşelerin bir listesini alırız.

Sadece Mathematica uzunlukta bir döngü olarak döngüler tedavi ise 1( AcyclicGraphQ @ CycleGraph[1, DirectedEdges -> True]verir Trueciddi), o zaman başka kurtarabilecek 26bayt:

FindCycle[#,∞,All][[-1,;;,1]]&

1
İhtiyacınız olmayacak MaximalByçünkü sonucu FindCyclezaten uzunluğa göre sıralanmıştır (son öğe en uzundur). Ayrıca, ilk argümanı ( FindCyclea \[DirectedEdge]yerine Graph) listesi olabilir . Artı, 2-byte kullanabilirsiniz ;;(= 1;;-1yerine 3-bayt) Alliçinde Partbir byte tasarrufu için. -22 bayt (58 bayt):(FindCycle[#,∞,All]/.{}->{Cases[#,v_v_]})[[-1,;;,1]]&
JungHwan Min

3

Haskell , 157154 bayt

import Data.List
g#l=nub[last$(e:d):[d|p==last q||e`elem`init d]|d@(p:q)<-l,[e,f]<-g,p==f]
h g=snd$maximum$((,)=<<length)<$>[]:until((==)=<<(g#))(g#)g

Çevrimiçi deneyin!

Bir demet bayt kaydettiğiniz için @Laikoni ve @Zgrab'a teşekkürler!

Bu çok verimsiz bir programdır:

Birinci fonksiyon #yollarının bir listesini alır lelemanlarını genişletmek ve denemeden (sayı listelerinin listesini) lolası her bir kenar (2 uzunluğunda bir listesi) prepending ile gher bir elemanı için l. Bu unsuru sadece olur lzaten döngüsü değildir ve başına eklenecektir olan yeni düğüm zaten unsuru içerdiği takdirde l. Zaten bir döngü ise, hiçbir şeyi başa eklemeyiz, ancak yeni yol listesine tekrar ekleriz, genişletebilirsek, genişletilmiş yolu yeni listeye ekleriz, aksi takdirde yeni listeye eklemeyiz .

Şimdi işlev h, sabit bir noktaya ulaşıncaya kadar bu yolları (kenarların listesinden başlayarak) art arda genişletmeye çalışır, yani başka bir yolu daha fazla genişletemeyiz. Bu noktada listemizde sadece döngüler var. O zaman sadece en uzun döngüyü seçmek meselesidir. Bir döngünün her olası döngüsel dönüşü tekrar bir döngü olduğu için, döngüler bu listede birden çok kez görünür.


Parantezleri bırakabilirsiniz (p:q)<-l.
Laikoni

Ve <$>yerine kullanmak mapbaşka bir bayt kaydetmek gerekir ((,)=<<length)<$>[]:.
Laikoni

@Laikoni Çok teşekkür ederim!
Kusur

Son çizgiden sonra fazladan alanınız var. Ayrıca, yapmak d@(p:q)<-lbayt tasarruf sağlar.
Zgarb

Oh, d@(p:q)gerçekten güzel, bana gösterdiğiniz için teşekkür ederim!
Kusur

2

Pyth, 20 bayt

eMefqhMT.>{eMT1s.pMy

Test odası

Örneklerde olduğu gibi kenarların bir listesini alır.

Açıklama:

eMefqhMT.>{eMT1s.pMy
eMefqhMT.>{eMT1s.pMyQ    Variable introduction
                   yQ    Take all subsets of the input, ordered by length
                .pM      Reorder the subsets in all possible ways
               s         Flatten
                         (This should be a built in, I'm going to make it one.)
   f                     Filter on (This tests that we've found a cycle)
    qhMT                 The list of first elements of edges equals
           eMT           The last elements
         .>   1          Rotated right by 1
        {                Deduplicated (ensures no repeats, which would not be a
                         simple cycle)
  e                      Take the last element, which will be the longest one.
eM                       Take the last element of each edge, output.

2

Bash + bsdutils, 129 bayt

sed 's/^\(.*\) \1$/x \1 \1 x/'|sort|(tsort -l>&-)|&tr c\\n '
 '|sed 's/x //g'|awk 'm<NF{m=NF;gsub(/[^0-9 ] ?/,"");print}'|tail -1

tsort tüm ağır kaldırmayı yapar, ancak çıktı biçimi oldukça benzersizdir ve uzunluk döngüleri 1'i algılamaz. Bunun GNU tsort ile çalışmadığını unutmayın.

Doğrulama

--- t1 ---
0
--- t2 ---
--- t3 ---
0 1
--- t4 ---
1 2 4 5
--- t5 ---
0 2 4 6 8
--- t6 ---
0 2 1 6 3 7 4 8 9 5
--- t7 ---
0 11 10 3 1 2 4 7 5 8 9 6

2

JavaScript (ES6), 173 163 156 145 139 bayt

@Neil sayesinde 5 bayt kaydedildi

f=(a,m,b=[])=>a.map(z=>!([x,y]=z,m&&x-m.slice(-1))&&b.length in(c=(n=m||[x],q=n.indexOf(y))?~q?b:f(a.filter(q=>q!=z),[...n,y]):n)?b=c:0)&&b

Test snippet'i


Kesinlikle düz bir eski düzeye geçme map size birkaç bayt kazandırır?
Neil

@Neil Olmak zorundaydı .filter().map() , bu yüzden neredeyse kesinlikle değil. Anahtar beni 10 bayt kurtardı (şu anda olduğu gibi tamamen golf oynamamış olsa da)
ETHproductions

Sana kullanarak anlama sonucunu kullanan, bu yüzden yerine görmüyorum a.filter(z=>!e).map(z=>d)kullanabilirsiniza.map(z=>e?0:d) .
Neil

Haklısın, 5 bayt tasarruf etmek için her şeyi birleştirebilirim. Ve ben de ihtiyacım olduğunu fark ettim a+a?:-)
ETHproductions 19:17

Düşürücü neyin yanlış olduğunu açıklayabilir mi? Yanlış çıktılar üretiyor mu?
ETHproductions

2

Haskell , 109108 bayt

import Data.List
f g=last$[]:[b|n<-[1..length g],e:c<-mapM(\_->g)[1..n],b<-[snd<$>e:c],b==nub(fst<$>c++[e])]

Bir kaba kuvvet çözümü: girişin uzunluğuna kadar artan uzunluktaki tüm kenar listelerini oluşturun, döngü olanları koruyun, sonuncuyu döndürün. Grafiği formatta alır [(1,2),(2,3),(2,4),(4,1)]. Çevrimiçi deneyin!

açıklama

f g=                    -- Define function f on input g as
  last$                 -- the last element of the following list
  []:                   -- (or [], if the list is empty):
  [b|                   --  lists of vertices b where
   n<-[1..length g],    --  n is between 1 and length of input,
   e:c<-                --  list of edges with head e and tail c is drawn from
    mapM(\_->g)[1..n],  --  all possible ways of choosing n edges from g,
   b<-[snd<$>e:c],      --  b is the list of second elements in e:c,
   b==                  --  and b equals
    nub(fst<$>c++[e])]  --  the de-duplicated list of first elements
                        --  in the cyclic shift of e:c.

Sonunda neler olduğunu anlayana kadar biraz zaman aldı, yolları / döngüleri kontrol etme kısmı gerçekten akıllı, hayret ediyorum!
Kusur

@flawr Teşekkürler! Görünüşe göre isaacg benden önce aynı algoritmayı kullandı.
Zgarb

0

MATLAB, 291 260 bayt

ABir kenarın bir (i,j)ile belirtildiği bir bitişiklik matrisi alır1 in A(i,j)ve Adiğer tüm kayıtlarda sıfırdır. Çıktı en uzun çevrimin listesidir. Hiç döngü yoksa liste boştur ve bir döngü varsa liste başlangıç ​​ve bitiş noktalarını içerir. 1Tabanlı indeksleme kullanır .

Bu çözüm, grafiklerle ilgili yerleşik işlevler kullanmaz.

function c=f(A);N=size(A,1);E=eye(N);c=[];for j=1:N;l=g(j);if numel(l)>numel(c);c=l;end;end;function p=g(p)if ~any(find(p(2:end)==p(1)))e=E(p(end),:)Q=find(e*A)k=[];for q=Q;if ~ismember(q,p(2:end))n=g([p,q]);if numel(n)>numel(k);k=n;end;end;end;p=k;end;end;end

Ne yazık ki bu, bir işlev içinde özyinelemeli bir işlev kullandığından TryItOnline'da çalışmaz. Biraz değişiklik yapmak octave-online.net üzerinde denemenizi sağlar .

En son test durumunda alternatif bir en uzun döngü buldum [0 2 1 4 3 5 7 8 9 11 10 6 0](bu gösterim 0 tabanlı indeksleme kullanıyor)

açıklama

Buradaki temel yaklaşım, her düğümden bir BFS gerçekleştirmemiz ve başlangıç ​​düğümü haricinde ara düğümlerden hiçbirini tekrar ziyaret etmememize dikkat etmemizdir. Bu fikirle tüm olası döngüleri toplayabilir ve en uzun olanı kolayca seçebiliriz.

function c=f(A);
N=size(A,1);
E=eye(N);
c=[]; % current longest cycle
for j=1:N;                                      % iterate over all nodes
    l=getLongestCycle(j);                       % search the longest cycle through the current node
    if numel(l)>numel(c);                       % if we find a longer cycle, update our current longest cycle
        c=l;
    end;

end;

    function p=getLongestCycle(p);              % get longest cycle from p(1) using recursion
        if ~any(find(p(2:end)==p(1)));          % if we just found a cycle, return the cycle do nothing else, OTHERWISE:
            e=E(p(end),:);                      % from the last node, compute all outgoing edges
            Q=find(e*A);                        
            k=[];                               
            for q=Q;                            % iterate over all outogoin edges
                if ~ismember(q,p(2:end));       % if we haven't already visited this edge,
                    n=getLongestCycle([p,q]);   % recursively search from the end node of this edge
                    if numel(n)>numel(k);       % if this results in a longer cycle, update our current longest cycle
                        k=n;
                    end;
                end;
            end;
            p=k;
        end;
    end; 
end
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.