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;
}


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