Implementacja algorytmu (grafowego)

Implementacja algorytmu (grafowego)
S8
  • Rejestracja:ponad 5 lat
  • Ostatnio:ponad 5 lat
  • Postów:16
0

Witajcie!

Liczę na Waszą pomoc. Mam taki oto problem z implementacją algorytmu (grafowego):

Dane wejściowe to przykład stabilnego małżeństwa G = (A ∪ B, E) z niekompletnymi listami i ścisłymi preferencjami. Celem jest obliczenie dopasowania (skojarzenia) M w G, które jest największym popularnym dopasowaniem. Więc chcemy znaleźć część zbioru (partycję) (L, R) i dopasowanie M, które jest dobre w odniesieniu do tej części zbioru i które jest R-doskonałe. Wierzchołki w R mogą być postrzegane jako „poszukiwane” wierzchołki, ponieważ wszystkie są dopasowane w M, a wierzchołki w L są wierzchołkami, które szukają partnerów w R.
Dla wygody będę odnosić się do elementów A i B odpowiednio jako mężczyzn i kobiet. Niech A0 ⊂ A i B0 ⊂ B będą odpowiednio zbiorami tych mężczyzn i kobiet, którzy nie są dopasowani w żadnym stabilnym dopasowaniu G = (A ∪ B, E). Każde stabilne dopasowanie w G pozostawia te same wierzchołki niedopasowane. Niech L1 = A0 ∪ B0. Zauważmy, że L1 jest zbiorem niezależnym. Niech R1 = V \ L1. Rozpoczynamy algorytm od części zbioru (L1, R1).
Algorytm jest iteracyjny, a w każdej iteracji część zbioru (L, R) jest aktualizowana przy użyciu algorytmu akceptacji/odrzucenia Gale-Shapleya* na bieżącym L i R. W ten sposób będziemy używać algorytmu Gale–Shapleya kilka razy w naszym algorytmie. Ten algorytm akceptacji/ odrzucenia (L, R) dla dowolnego L ⊂ A ∪ B i R = V \ L podałem poniżej. Podprogram ten opisuje algorytm Gale – Shapleya na grafie „dwudzielnym” otrzymanym przez umieszczenie L na lewej i R po prawej stronie i zbiór krawędzi ograniczony do E ∩ (L × R); tutaj wierzchołki L „oświadczają się” wierzchołkom R.

Problem mam z implementacją Algorytmu 1. Poniżej są pseudokody obu algorytmów oraz kod Algorytmu 0 (w nim powinno być już wszystko OK).

*Algorytm akceptacji/odrzucenia Gale'a-Shapleya (zwany dalej "Algorytmem 0") polega na kolejnych rundach składania i przyjmowania lub odrzucania ofert. Każdy kawaler i każda panna ma swój ranking (listę preferencji). Każda z panien przyjmuje najlepszą z ofert, ale nie jest to akceptacja ostateczna. W kolejnej rundzie odrzuceni kawalerowie składają kolejne oferty kolejnym pannom ze swoich list. Jeśli któraś z nich otrzyma propozycję korzystniejszą niż ta warunkowo przyjęta wcześniej, może wymienić partnera. Procedura kończy się dopiero wtedy, gdy wszyscy mają swoją parę.

Algorytm 0. Algorytm akceptacji/odrzucenia:

Kopiuj
M = Ø
while jest jakieś u ∈ L niedopasowane w M, które nie zostało jeszcze odrzucone przez żadnego z kandydatek\kandydatów w R 
do
 u oświadcza się najbardziej preferowanemu kandydatowi\kandydatce v ∈ R, który nie odrzucił u
 if v woli u od M(v) then
 M(v) = u //Więc wierzchołek, który był poprzednim partnerem w M, został teraz odrzucony przez v. 
 else
 v odrzuca u
 end if
end while
Zwróć M

Algorytm 1. Wejście: G = (A ∪ B, E) z listami ścisłych preferencji
Niech S będzie stabilnym dopasowaniem uzyskanym przez algorytm akceptacji/odrzucenia na
(A, B). {To znaczy, mężczyźni proponują, a kobiety decydują.}
Niech L1 = zbiór wierzchołków pozostających niedopasowanymi w S; niech R1 = V \ L1
i = 1

Kopiuj
while TRUE do
   oblicz dopasowanie Mi poprzez algorytm akceptacji/odrzucenia na (Li,Ri)
   if Mi jest Ri-doskonałe then zwróć Mi
     niech Ai ⊂ A będzie zbiorem mężczyzn w Ri, którzy są niedopasowani w Mi
   L`i = Li ∪ Ai oraz R`i = V \ L`i 
   oblicz dopasowanie M`i poprzez algorytm akceptacji/odrzucenia na (L`i, R`i)
   if M`i jest R`i-doskonałe then zwróć M`i
   niech Bi będzie zbiorem wierzchołków w R`i pozostających niedopasowanymi przez M`i

   Li+1 = Li ∪ Bi oraz Ri+1 = V \ Li+1
   i = i + 1
end while

Kod Algorytmu 0:

Kopiuj
#include <cstdio>
#include <cstring>
#include <queue>
#include <stdlib.h>
using namespace std;

// Mężczyźni i kobiety są reprezentowani przez liczby całkowite 1 ... N

// PrefM to lista preferencji wszystkich mężczyzn do wszystkich kobiet.
// PrefM[m][i] = k jeśli k jest na i-tej pozycji na liście preferencji m

// PrefK to lista preferencji wszystkich kobiet do wszystkich mężczyzn.
// PrefK[k][i] = m jeśli m jest na i-tej pozycji na liście preferencji k

// Ranking podaje ranking każdego mężczyzny na liście preferencji każdej kobiety
// Ranking[k][m] = i jeśli PrefK [k] [i] = m

// Partner daje bieżący "związek" każdej kobiety
// Partner[k] = m jeśli k jest obecnie związana z m

// Next podaje indeks następnej kobiety, której ma się oświadczyć wg listy preferencji każdego mężczyzny
// Next[m] = i jeśli m oświadczył się wszystkim k oraz PrefM[m][j] = k dla j = 1 ... i-1, ale nie PrefM[m][i]

int Ranking[505][505], PrefM[505][505], PrefK[505][505], Next[505], Partner[505];
int T, N, i, j, m, k;
queue <int> WolniM; //Wolni mężczyźni

void wczytaj() {
    printf("Liczba kobiet i mezczyzn: ");
    scanf("%d", &N);
    for (i = 1; i <= N; i++) {
            k=i; //scanf("%d", &k);
            printf("Preferencje kobiety nr %d:\n", k);
            for (j = 1; j <= N; j++)
                scanf("%d", &PrefK[k][j]);
        }
    for (i = 1; i <= N; i++) {
            m=i;//scanf("%d", &m);
            printf("Preferencje mezczyzny nr %d:\n", m);
            for (j = 1; j <= N; j++)
                scanf("%d", &PrefM[m][j]);
        }

    for (i = 1; i <= N; i++)
        for (j = 1; j <= N; j++)
            Ranking[i][PrefK[i][j]] = j;

    memset(Partner, 0, N * sizeof(int));

    for (i = 1; i <= N; i++) {
            WolniM.push(i);
            Next[i] = 1;
        }
}           

void algorytm0 () {

        while (!WolniM.empty())    {
            m = WolniM.front();
            //printf("\nm=%d Next[m]=%d\n", m, Next[m]);
            k = PrefM[m][Next[m]++];
            //printf("k=%d Next[m]=%d\n", k, Next[m]);
            if (Partner[k] == 0)   {
                Partner[k] = m;
                WolniM.pop();
            } else if (Ranking[k][m] < Ranking[k][Partner[k]])  {
                WolniM.pop();
                WolniM.push(Partner[k]);
                Partner[k] = m;
            }
        }
}   
void wypisz() {
    printf("\nDobrane pary (m, k):\n");
        for (k = 1; k <= N; k++)
            printf("%d, %d\n", Partner[k], k);
}
int main()  {

    printf("Liczba testow: ");
    scanf("%d", &T);
    while (T--) {

        wczytaj();
        algorytm0();
        wypisz();

    }
    system("pause");
    return 0;
}
S8
Nic. Nikt tam nie mógł pomóc. Ewentualnie można usunąć.
Delor
Jeżeli nie załapałeś to w nim zasugerowano Ci ten dział: https://4programmers.net/Forum/Og%C5%82oszenia_drobne
S8
To znaczy, że tutaj też nie mam co liczyć na pomoc? :/
Delor
Dostaniesz pomoc. :) Tylko uwzględnij uwagi z poprzedniego wątku. Naprawdę, to nie są jakieś wymysły ale znaczne ułatwienie dla innych.
_13th_Dragon
  • Rejestracja:ponad 19 lat
  • Ostatnio:2 miesiące
0
Stachu87 napisał(a):

Algorytm 0. Algorytm akceptacji/odrzucenia:
...
u oświadcza się najbardziej preferowanemu kandydatowi\kandydatce v ∈ R, który nie odrzucił u
...
Kod Algorytmu 0:

Kopiuj
...
            k = PrefM[m][Next[m]++];
...

W kodzie zaś oświadcza się kolejnej kandydatce.
Musisz użyć tablicy Ranking.


Wykonuję programy na zamówienie, pisać na Priv.
Asm/C/C++/Pascal/Delphi/Java/C#/PHP/JS oraz inne języki.
edytowany 1x, ostatnio: _13th_Dragon
S8
  • Rejestracja:ponad 5 lat
  • Ostatnio:ponad 5 lat
  • Postów:16
0
_13th_Dragon napisał(a):
Stachu87 napisał(a):

Algorytm 0. Algorytm akceptacji/odrzucenia:
...
u oświadcza się najbardziej preferowanemu kandydatowi\kandydatce v ∈ R, który nie odrzucił u
...
Kod Algorytmu 0:

Kopiuj
...
            k = PrefM[m][Next[m]++];
...

W kodzie zaś oświadcza się kolejnej kandydatce.
Musisz użyć tablicy Ranking.

Następnej, ale zaczyna od tej najbardziej preferowanej. Pierwsza w kolejce jest najbardziej preferowana. Ja bym nic nie zmieniał w kodzie algorytmu 0. Dziękuję za zainteresowanie.
Jednak potrzebuję raczej pomocy z Algorytmem 1.

TomaszLiMoon
  • Rejestracja:prawie 10 lat
  • Ostatnio:około 7 godzin
  • Postów:530
0
S8
Dzięki za odp, ale czy nie wstawiałeś tutaj kodu? Tak pojawiło mi się w powiadomieniu o 9:34
TomaszLiMoon
Tak, wstawiłem przez pomyłkę kod odnoszący się do algorytmu 0.
S8
Ty też coś widziałeś nie tak w tym kodzie...?
TomaszLiMoon
Nie, przerobiłem go tylko do postaci czystego C++.
S8
  • Rejestracja:ponad 5 lat
  • Ostatnio:ponad 5 lat
  • Postów:16
0
TomaszLiMoon napisał(a):

Zobacz https://github.com/dilsonpereira/Minimum-Cost-Perfect-Matching

Nie wiem, czy to nie jest tam zbyt skomplikowane... ale dzięki za odp i link :)

edytowany 1x, ostatnio: Stachu87
Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)