Algoritmus pro
vyhledávání souvislých (silně souvislých) komponent za použití Floydova algoritmu
Michal Radecký, L97085
Princip algoritmu
Algoritmus je založen na zpracování výsledků Floydova
algoritmu. Tj. z matice dosažitelnosti určí jednotlivé komponenty.
Nejprve je tedy nutné na zadaný graf aplikovat Floydův
algoritmus, který z matice cen, vytvoří matici dosažitelnosti. V našem případě, je
zbytečné pracovat s kompletní maticí cen, a je postačující pracovat s maticí, kde
jsou ceny nahrazeny jedničkou.
Po vytvoření této matice pak aplikujeme algoritmus zařazování
vrcholů do komponent. Tento algoritmus je založen na zjišťování dosažitelných
vrcholů z výchozího vrcholu a naopak, dosažitelnost z dosažených vrcholů zpět do výchozího
vrcholu. Je-li tato podmínka splněna, je dosažený vrchol zařazen do stejné
komponenty, jako byl vrchol výchozí. Algoritmus končí, jakmile jsou všechny vrcholy
zařazeny do některé z komponent.
Implementace algoritmu Funkce se tedy volá: Zdrojový kód
Vlastní implementace je v jedné funkci, která jako vstupní
parametr dostává celou strukturu grafu a alokovane pole, a jak výsledek vrací ukazatel na pole, které
k jednotlivým vrcholům přiřazuje číslo příslušné komponenty. Vzhledem k předávání dat, jsou vráceny čísla komponent postupně, nikoliv podle čísla vrcholů
Jako první krok je vytvoření matice A, jako
dvojrozměrného dynamického pole o rozměrech [počet vrcholů][počet vrcholů]. Dále
je toto pole inicializováno na počáteční hodnotu (všechny prvky jsou X, hlavní
diagonála pak 0). Nakonec je podle struktury grafu jednotlivým prvkům přiřazena
hodnota (viz.výše).
Dalším krokem je vytvoření matice dosažitelnosti,
to je provedeno pomocí tří vnořených cyklů a trojůhelníkové nerovnosti.
Poslední část algoritmu potřebuje ke své činnosti ještě
vytvořené pole K o velikosti [počet vrcholů]. Prvky tohoto
pole se inicializují na hodnotu X. Dále se vybere první prvek, jehož hodnota v K je X.
Pak se prochází řádek matice odpovídající vybranému vrcholu a kontroluje se,
jestli jsou vrcholy dosažitelné z vybraného vrcholu a zpět. Platí-li to, je zkoumaný
vrchol v poli K označen číslem komponenty. Tato část algoritmu
je uzavřena v cyklu, který probíhá tak dlouho, dokud počítadlo zařazených vrcholů
není rovno počtu vrcholů.
ukazatel
= Funkce(Graf);
, kde ukazatel je ty pointer na int a Graf je ukazatel na
strujturu grafu (TGraf).
Po provedení funkce je tedy ukazatel nastaven na první
prvek dynamicky vytvořeného pole K a je nutné ho po zpracovácní dealokovat příkazem
delete
[počet vrcholů]ukazatel;
#define X 10000 //nedosazitelny vrchol, zatim
nezakomponentovany vrchol musi byt hodne velke int cislo
int *Funkce(TGraf *graf, int *K)
{
int i,j,k; //pomocne
int **A; //matice cen
//dynamicka inicializace matice
A = new int*[graf->nvrch];
for (i=0;i<(graf->nvrch);i++)
A[i]= new int[graf->nvrch];
//naplneni matice
for(i=0;i<(graf->nvrch);i++)
for(j=0;j<(graf->nvrch);j++)
A[i][j]=X; //nejprve jsou vsechny
vrcholy nedosazitelne
for(i=0;i<(graf->nvrch);i++)
A[i][i]=0; //na diagonale nuly
for(i=0;i<(graf->nhran);i++)
A[graf->phran[i].pv-1][graf->phran[i].kv-1]=1; //existujici
hrany
//Floyduv algoritmus pro urceni dosazitelnosti
for(k=0;k<(graf->nvrch);k++)
for(i=0;i<(graf->nvrch);i++)
for(j=0;j<(graf->nvrch);j++)
if(A[i][j]>(A[i][k]+A[k][j]))
A[i][j]=A[i][k]+A[k][j]; //trojuhelnikova nerovnost
//algoritmus pro zarazovani vrcholu do komponentu
for(i=0;i<(graf->nvrch);i++) K[i]=X; //inicializace, vsechny
vrcholy jsou nezarazene
int pocet_zakomp=0; //pocitadlo jiz zarazenych vrcholu, slouzi k
urceni ukonceni cyklu
int cislo_komp=0; //pocitadlo aktualniho cisla komponenty
int vyb_vrch; //aktualni vrchol - vychozi
while(pocet_zakomp<(graf->nvrch)) //dokud nejsou zarazeny
vsechny
{
for(i=0;i<(graf->nvrch);i++) if (K[i]==X)
{cislo_komp++;vyb_vrch=i;i=graf->nvrch;}
//nalezeni prvniho nezarazeneho vrcholu
K[vyb_vrch]=cislo_komp; //zarazeni vrcholu do komponenty
pocet_zakomp++;
for(i=0;i<(graf->nvrch);i++) //cyklus pro
kontrolu dosazitelnosti z vybraneho
//vrcholu a zpet
if((A[vyb_vrch][i]!=0)&&(A[vyb_vrch][i]!=X)&&(A[i][vyb_vrch]!=0)&&(A[i][vyb_vrch]!=X))
{
K[i]=cislo_komp; //je-li vrchol dosazitelny z vybraneho a naopak,
//je zarazen do komponenty vybraneho
vrcholu
pocet_zakomp++;
}
}//konec while
return K;
//funkce vraci ukazatel na pole, jehoz velikost je pocet vrcholu v
grafu
//a jednotlive hodnoty symbolizuji cislo komponenty tj. 1,1,2,3 atd.
}