爲了學習這個優化啊,把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;
}