Vytvorte trídu, která bude reprezentovat , nezáporne ohodnocený graf (sít mest), a implementujte metodu hledání minimální cesty z daného uzlu (mesta) do vsech ostatních a k ní program podle následujících pozadavku.
Predpokládejte, ze graf je ulozen v textovém souboru, kde jednotlivé rádky obsahují informaci následujícího tvaru:
mestoA mestoB vzdálenostkterá urcuje vzdálenost z mestaA do mestaB. Vzdálenosti jsou celocíselné, jednotlivé vstupní polozky jsou oddeleny bílým znakem nebo jejich kombinací.
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <map>
#include <iomanip>
using namespace std;
class graf
{
private:
struct udaje{string cesta;int vzdialenost;};
string z_mesta,do_mesta;
int pocet_miest,vzdialenost;
multimap<string,string> mesta;
multimap<string,udaje>cesty_z_mesta;
multimap<string,int> dlzka_cesty;
multimap<string,string>::iterator tm;
multimap<string,int>::iterator td_c;
multimap<string,udaje>::iterator tczm;
public:
graf(){};
graf(const graf& a);
~graf(){};
int read(char * file); //nacitanie vstupneho grafu
int find(string from,string to); //najde from->to
void write_out_ways(); //vypise cesty
private:
bool control(string from,string to); //ci obsahuje subor mesta
bool find(string from); //najde vsetky mesta kam sa da dostat
};
graf::graf(const graf& a):mesta(a.mesta),dlzka_cesty(a.dlzka_cesty)
{pocet_miest=a.pocet_miest;}
//======================= nacitanie vstupneho grafu ============================
int graf::read(char *file)
{
string mesto1,mesto2,pom;
ifstream in(file,ios::in);
if(!in) return 1;
for(;;)
{
if(!(in>>mesto1>>mesto2>>vzdialenost)) break;
for(unsigned int i=0;i<mesto1.length();i++) mesto1[i]=toupper(mesto1[i]);
for(unsigned int i=0;i<mesto2.length();i++) mesto2[i]=toupper(mesto2[i]);
if(mesto1>mesto2){string pom;pom=mesto1;mesto1=mesto2;mesto2=pom;}
mesta.insert(make_pair(mesto1,mesto2));
mesta.insert(make_pair(mesto2,mesto1));
dlzka_cesty.insert(make_pair(mesto1+" "+mesto2,vzdialenost));
if(mesto1==mesto2) return 2;
if(vzdialenost<1) return 2;
}
in.close();
mesto2=mesto1="";pocet_miest=0; //spocitat pocet miest
for(tm=mesta.begin();tm!=mesta.end();++tm)
{mesto2=tm->first;
if(mesto2!=mesto1) pocet_miest++;
mesto1=mesto2;
}
//odstranenie duplicitnych ciest
for(td_c=dlzka_cesty.begin();td_c!=dlzka_cesty.end();td_c++)
{mesto1=td_c->first;vzdialenost=td_c->second;
if(mesto1==mesto2)
{--td_c;
if(td_c->second >=vzdialenost) dlzka_cesty.erase(td_c++);
else dlzka_cesty.erase(++td_c);
}
mesto2=mesto1;
}
return 0;
}
//============================= hladanie cesty =================================
bool graf::find(string from)
{
for(tczm=cesty_z_mesta.begin();tczm!=cesty_z_mesta.end();tczm++)
//vynulovanie
cesty_z_mesta.erase(tczm);
bool chyba=false;
udaje najdene,nacitane;
int *uzol=new int[pocet_miest],cislo_uzlu=0,
*cislo_na_uzle=new int[pocet_miest],kontrola;
for(int i=0;i<pocet_miest;i++) cislo_na_uzle[i]=0;
string *across,mesto1,mesto2;
across=new string[pocet_miest];
across[0]=z_mesta;
//----------------- hlavny cyklus hladania ------------------------------------
for(;;)
{kontrola=1;
if(cislo_uzlu<0 ||cislo_uzlu==pocet_miest) break;
if(across[0]!=z_mesta)break;
mesto1=across[cislo_uzlu];
tm=mesta.find(mesto1);
for(int i=0;i<cislo_na_uzle[cislo_uzlu];i++) ++tm;
if(tm==mesta.end())
{cislo_na_uzle[cislo_uzlu]=0;
across[cislo_uzlu]="";
cislo_uzlu--;
cislo_na_uzle[cislo_uzlu]++;
continue;
}
if(tm->first!=mesto1)
{cislo_na_uzle[cislo_uzlu]=0;
across[cislo_uzlu]="";
cislo_uzlu--;
cislo_na_uzle[cislo_uzlu]++;
continue;
}
//nasiel mesto1
kontrola=0;
for(int i=0;i<=cislo_uzlu;i++)
if(across[i]==tm->second){cislo_na_uzle[cislo_uzlu]++;kontrola=1;break;}
if(kontrola) continue;
cislo_uzlu++;
across[cislo_uzlu]=tm->second;
//---------------------------------nasiel nejaku cestu-----------------------
{
chyba=true;
vzdialenost=0;
for(int i=1;i<=cislo_uzlu;i++) //najdenie dlzky cesty
{
if(across[i-1]<across[i])
td_c=dlzka_cesty.find(across[i-1]+" "+across[i]);
else
td_c=dlzka_cesty.find(across[i]+" "+across[i-1]);
vzdialenost+=td_c->second;
}
najdene.cesta=across[0];
for(int i=1;i<pocet_miest && across[i]!="";i++)
najdene.cesta+=" -> "+across[i];
najdene.vzdialenost=vzdialenost;
tczm=cesty_z_mesta.find(z_mesta+" "+tm->second);
if(tczm==cesty_z_mesta.end())
cesty_z_mesta.insert(make_pair(z_mesta+" "+tm->second,najdene));
else // jedna cesta uz bola najdena (treba porovnat vzdialenosti)
{
nacitane=tczm->second;
if(nacitane.vzdialenost>najdene.vzdialenost)
{
cesty_z_mesta.erase(tczm);
cesty_z_mesta.insert(make_pair(z_mesta+" "+tm->second,najdene));
}
}
}
//---------------------------------------------------------------------------
}
delete[] across;
delete[] uzol;
delete[] cislo_na_uzle;
return chyba;
}
//==============================================================================
int graf::find(string from,string to)
{
if (!control(from,to)) return 1;
if (!find(z_mesta)) return 2;
if(do_mesta!="")
for(tczm=cesty_z_mesta.begin();tczm!=cesty_z_mesta.end();tczm++)
{
if(tczm->first!=z_mesta+" "+do_mesta) cesty_z_mesta.erase(tczm);
}
if(!cesty_z_mesta.size()) return 2;
return 0;
}
//====================== hladanie existencie miest =============================
bool graf::control(string from,string to)
{
string pom1,pom2;
//------------------------------------------------------------------------------
// kontrola ci obsahuje from
for(tm=mesta.begin();tm!=mesta.end();tm++)
{ if( ((tm->first).find(from))==0)
{
if(tm->first.length()<from.length()) continue;
if(tm->first==from) {pom1=tm->first;break;}
if(pom1.length()==0) pom1=tm->first;
else if( pom1!=tm->first) return false;
}
}
if(pom1=="") return false;
//------------------------------------------------------------------------------
// kontrola ci obsahuje "to"
if(to!="")
for(tm=mesta.begin();tm!=mesta.end();tm++)
{ if( ((tm->first).find(to))==0)
{
if(tm->first.length()<from.length()) continue;
if(tm->first==to) {pom2=tm->first;break;}
if(pom2.length()==0) pom2=tm->first;
else if( pom2!=tm->first) return false;
}
}
if(to!="" && pom2=="") return false;
z_mesta=pom1;
do_mesta=pom2;
return true;
}
//======================= vypis najkratsej cesty ===============================
void graf::write_out_ways()
{
udaje nacitane;
if(do_mesta!="")
cout<<"Cesta: "<<z_mesta<<" -> "<<do_mesta<<endl;
else
cout<<"Cesty z mesta"<<" \""<<z_mesta<<"\""<<endl;
cout<<"\n"<<setw(67)<<left<<setfill(' ')<<"Cesta";
cout<<"Vzdialenost"<<endl;
cout<<setfill('=')<<setw(80)<<""<<endl;
for(tczm=cesty_z_mesta.begin();tczm!=cesty_z_mesta.end();tczm++)
{
nacitane=tczm->second;
cout<<setw(70)<<left<<setfill(' ')<<nacitane.cesta;
cout<<" ("<<nacitane.vzdialenost<<')'<<endl;
cout<<setfill('-')<<setw(80)<<""<<endl;
}
}
//=================================MAIN=========================================
int control;
int main(int argc, char *argv[])
{
if (argc>=3) //- - - - - - - osetrenie parametrov - - - - - - - - -
{
ifstream input(argv[1]);
if (!input)
{cout<<"Nepodarilo sa otvorit vstupny subor."<<endl;return 2;}
else input.close();
}
else
{
cout<<"\nZadaj spravne parametre:\n\n"
<<" graf \"subor_s_grafom\" \"z_mesta\" \"do_mesta\"\n"
<<" -pamameter \"do_mesta\" je nepovinny\n"<<endl;
return 1;
}
//-----------------------parametre su OK ---------------------------------------
cout<<"\nGraf je zadany v subore: "
<<"\""<<argv[1]<<"\""<<endl;
string a=argv[2],b;
if(argc>=4)
b=argv[3];
else
b="";
for(unsigned int i=0;i<a.length();i++) a[i]=toupper(a[i]);
for(unsigned int i=0;i<b.length();i++) b[i]=toupper(b[i]);
graf siet;
control=siet.read(argv[1]);
if(control)
{
cout<<"Nekonzistencia vstupnych dat!"<<endl;
return control+10;
}
graf siet2=siet;
control=siet2.find(a,b);
if(control)
{if(control==2) cout<<"Cesta nenexistuje!"<<endl;
if(control==1) cout<<"Mesto nebolo najdene v grafe, upresnite nazov!"<<endl;
return control+20;
}
//return 22-nenasiel cestu
//return 21-nenasiel mesto
else
siet2.write_out_ways();
return 0;
}