#include<iostream>
#include<vector>
#include<queue>

using namespace std;

class edge
{
public:
    int nbr;
    int wt;
};

vector<vector<edge>> graph;

void addedge(int v1, int v2, int wt)
{

    edge e1;
    e1.nbr = v2;
    e1.wt = wt;
    graph[v1].push_back(e1);

    edge e2;
    e2.nbr = v1;
    e2.wt = wt;
    graph[v2].push_back(e2);
}

class dpair
{
    public:
    int v;
    int cost;
    string psf;

dpair(int a,int b,string s)
{
    v=a;
    cost=b;
    psf=s;
}
dpair()
{

}

bool operator>(const dpair &other)const
{
  return cost > other.cost;
}

};


void djikstra(int n)
{
 priority_queue<dpair,vector<dpair>,greater<dpair>> pq;
vector<bool> check(graph.size(),false);
 dpair dp(n,0,to_string(n));

 pq.push(dp);

 while(pq.size()>0)
{
    dpair temp=pq.top();
    pq.pop();

    if(check[temp.v]==true){
    continue;
    }

    check[temp.v]=true;

   
   cout<<temp.v<<" @ "<<temp.cost<<" via "<<temp.psf<<endl;

    for(int i=0;i<graph[temp.v].size();i++)
   {
       
    if(check[graph[temp.v][i].nbr]==false)
       {
           dpair x(graph[temp.v][i].nbr, temp.cost + graph[temp.v][i].wt,temp.psf + to_string(graph[temp.v][i].nbr));
           pq.push(x);
       } 
}


}



}


int main()
{

    graph.push_back(vector<edge>());
    graph.push_back(vector<edge>());
    graph.push_back(vector<edge>());
    graph.push_back(vector<edge>());
    graph.push_back(vector<edge>());
    graph.push_back(vector<edge>());
    graph.push_back(vector<edge>());

    addedge(0, 1, 10);
    addedge(1, 2, 10);
    addedge(2, 3, 10);
    addedge(0, 3, 40);
    addedge(3, 4, 2);
    addedge(4, 5, 3);
    addedge(5, 6, 3);
    addedge(4, 6, 8);

    djikstra(0);


}