Dijkstra + 優先隊列 + 鄰接表優化

爲了學習這個優化啊,把Dijkstra,和優先隊列,還有map,還有pair,還有vector,之前很散的知識又重現看了一遍

然後讀了好久的dalao下面這個代碼,現在算是懂了一些些了。


#include <iostream>
#include <queue>
#include <map>
#include <functional>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <cstring>
using namespace std;

const int N=205;
const int INF=1<<30;

typedef pair<int,int>pii;//相當於struct pii;後面可pii p1;pii p2;之類的

string src,ed;
int n,m;//點,邊
int dis[N];
struct edge//用結構體存放邊和權值
{
    int u;
    int v;
    int w;
    edge(){}//構造函數
    edge(int uu,int vv,int ww):u(uu),v(vv),w(ww){}
};

map<string,int> M;//給的點是字符串,map轉換成數字
vector<edge>G[N];//vector數組

void init()
{
    M.clear();//對於每個case,每次循環對M清空
    int cnt=0;//爲了給每個字符串key,一個value,value只就是cnt++
    cin>>n>>m;//點數和邊數
    string u,v;//輸入字符型的節點,用於一會輸入
    int w;//每條邊的權值
    for(int i=1;i<=m;i++)
    {
        cin>>u>>v>>w;//輸入邊和權值
        if(!M.count(u))//如果M(map定義的)裏面沒有這個key,就將他插入將他對應爲++cnt值,如果有,不變,意味着,cnt不變,這時的u仍爲原來的value值
        M.insert(make_pair(u,++cnt));//用make_pair()函數,將key和value(給每個的編號)值插入M(map)
        if(!M.count(v))//同理
            M.insert(make_pair(v,++cnt));//這些都是爲了將字符串用數字編號表示

        edge E1(M[u],M[v],w);//用struct構造兩個方向的邊,且用構造函數賦值,兩點的編號,和邊的權值
        edge E2(M[v],M[u],w);//從而合成,無向的圖-->這樣得到兩條邊的信息

        G[M[u]].push_back(E1);//建立鄰接表,用vector表示,將這一條邊E1壓入鄰接表
        G[M[v]].push_back(E2);//另一條邊也壓入鄰接表
    }
    cin>>src>>ed;//輸入最終要求的,起點和終點,編號就是M[src],M[ed]
    for(int i=1;i<=m;i++)
    {
        dis[i]=(i==M[src]?0:INF);//初始化dis,dis裏存的是,起點src到各點的最短距離,dis[src]爲零,其他的初始化爲inf
    }
}

void Dijkstra()
{
    priority_queue<pii,vector<pii>,greater<pii> > que;//優先隊列,用pair,相當於一個新的結構體,有兩個屬性
    que.push(make_pair(0,M[src]));//用make_pair()將起點壓入優先隊列(即通過pair的兩個屬性)。距離和編號
    while(!que.empty())//如果優先隊列不是空的
    {
        pii tmp=que.top();//聲明一個新的pii,tmp。讓tmp存放優先隊列的,隊前的元素,因爲是greater,即que.top就是目前隊列裏最短距離
        //tmp擁有了優先隊列裏最小值的兩個屬性分別賦給了tmp.first(距離)和tmp.second(編號)
        que.pop();//把這個點清掉(開始時,清理的是起點)
        int x=tmp.second;//x存放編號
        if(tmp.first!=dis[x])//如果距離和他帶的點的距離不一樣了,說明這個點處理過了,continue跳過這個點
            continue;

        for(int i=0;i<G[x].size();i++)
        {
            int y=G[x][i].v;//y存放鄰接表的的v值,
            int w=G[x][i].w;
            if(dis[y]>dis[x]+w)//如果距離
            {
                 dis[y] = dis[x] + w;
                que.push(make_pair(dis[y],y));
            }
        }
    }
}

int main()
{
    int ttt;
    cin>>ttt;
    while(ttt--)
    {
        init();//初始化,和輸入
        Dijkstra();//dijkstra函數
        if(dis[M[ed]]==INF) cout<<"-1"<<endl;//如果不聯通,輸出-1
        else cout<<dis[M[ed]]<<endl;//可以寫成,cout<<(dis[M[ed]]==INF?-1:dis[M[ed]]])<<endl;
    }
    return 0;
}<div>輸入數據:</div><div>1
6 9
D E 13
B C 9
A B 1
A C 12
B D 3
E C 5
D C 4
D F 15
E F 4
A F
輸出數據:</div><div>17</div>


然後打算自己敲一遍簡化版,就是將輸入的字符串變成了輸入編號

就省去了map<>的使用

簡化了好多,再寫一遍,還是要理解才能記住。


#include <iostream>
#include <cstring>
#include <vector>
#include <cstdio>
#include <cstring>
#include <queue>
#include <functional>
#include <algorithm>
using namespace std;
const int N=205;
const int inf = 1<<30;
int src,ed,n,m;
int dis[N];
typedef pair<int,int>pii;

struct edge
{
    int u;
    int v;
    int w;
    edge() {}
    edge(int uu,int vv,int ww):u(uu),v(vv),w(ww) {}
};
vector<edge>G[N];
void Init()
{
    int uu,vv,ww;
    cin>>n>>m;
    for(int i=0; i<m; i++)
    {
        cin>>uu>>vv>>ww;
        edge E1(uu,vv,ww);
        edge E2(vv,uu,ww);
        G[uu].push_back(E1);
        G[vv].push_back(E2);
    }
    cin>>src>>ed;
    for(int i=1; i<=m; i++)
        dis[i]=(i==src?0:inf);
}

void Dijkstra()
{
    priority_queue<pii,vector<pii>,greater<pii> > que;
    que.push(make_pair(0,src));
    while (!que.empty())
    {
        pii temp = que.top();
        que.pop();
        int x=temp.second;
        if(dis[x]!=temp.first)
        {
            continue;
        }
        for(int i=0; i<G[x].size(); i++)
        {
            int y=G[x][i].v;
            int w=G[x][i].w;
            if(dis[y]>dis[x]+w)
            {
                dis[y]=dis[x]+w;
                que.push(make_pair(dis[y],y));//算法核心
            }
        }
    }

}
int main()
{
    int ttt;
    cin>>ttt;
    while(ttt--)
    {
        Init();
        Dijkstra();
        cout<<(dis[ed]==inf?-1:dis[ed])<<endl;
    }
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章