为了学习这个优化啊,把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;
}