写在前面的话:
- 接下来是Kuangbin的专题二最短路。朴素的Dijkstra只写这一次,以后不出意外都默认是堆优化(当然是正确的堆优化啦)。
- 这里首次提出点态的概念,目的是防止大家混淆,点态一般是指所定义的结构体,如本题中包含 id 和 dis 两个元素。点态可能有多个,点只能有一个。
思路:
- 邻接矩阵存图,无向正权图,求解最短路。
- Dijkstra。
- 下面依次是朴素,虚假堆优化,弱智堆优化算法,和正确的堆优化算法(…)。
- 可是,虚假的堆优化和正确的堆优化时间是一样的(…)。
- 朴素:查找最短距离点,vis置true,松弛。
- 虚假:您不用看了,使用点并扔掉,vis置true,松弛顺便找到下一个点,实际上从头到尾队列里都只有一个点(…)。至于为什么能够优化一些些,我想是把查找和松弛合并了的缘故。
- 弱智:所有未用到的点进入优先队列,然后每次更新都会扔掉很多点,您也不用看了,纯粹是我瞎想出来的副产品。
- 真正:把每次松弛的点都加入队列,然后加入关键的一行判断(如果目前弹出的点态,在入队之后被别的点松驰过,就舍弃这个点态,而应当使用的点态在其出现后也已入队,所以没有问题)。
代码:
#include <iostream>
#include <cstring>
#include <queue>
#include <algorithm>
#define INF 0x3f3f3f3f
using namespace std;
const int maxn = 1005;
int N,U;
int mp [maxn][maxn];
bool vis[maxn];
int dis[maxn];
int ans;
void Dijkstra(){
dis[U] = 0;
vis[U] = true;
while(true){
int temp_id;
int temp_dis = INF;
for(int i=1;i<=U;i++){
if(vis[i])
continue;
if(temp_dis > dis[i])
temp_dis = dis[i], temp_id = i;
}
if(temp_id == 1){
ans = temp_dis;
return ;
}
vis[temp_id] = true;
for(int i=1;i<=U;i++){
if(vis[i])
continue;
dis[i] = min(dis[i] , dis[temp_id] + mp[temp_id][i]) ;
}
}
}
int main(){
memset(mp,INF,sizeof(mp));
for(int i=1;i<=U;i++)
mp[i][i] = 0;
memset(dis,INF,sizeof(dis));
memset(vis,false,sizeof(vis));
cin>>N>>U;
for(int i=1;i<=N;i++){
int x,y,w;
cin>>x>>y>>w;
mp[x][y] = mp[y][x] = min(mp[x][y] , w);
if(x == U)
dis[y] = mp[U][y];
if(y == U)
dis[x] = mp[U][x];
}
Dijkstra();
cout<<ans<<endl;
return 0;
}
#include <iostream>
#include <queue>
#include <cstring>
#include <algorithm>
#define INF 0x3f3f3f3f
using namespace std;
const int maxn = 1005;
int N,U;
int mp[maxn][maxn];
bool vis[maxn];
int dis[maxn];
struct node{
int id;
int dis;
node(int id,int dis) : id(id) , dis(dis) {} ;
friend bool operator > (const node & a , const node & b)
{
return a.dis > b.dis;
}
};
priority_queue<node , vector<node> , greater<node> > Q;
int ans;
void Init(){
memset(mp,INF,sizeof(mp));
for(int i=1;i<=U;i++)
mp[i][i] = 0;
memset(dis,INF,sizeof(dis));dis[U]=0;
memset(vis,0,sizeof(vis));
return ;
}
void Dijkstra(){
Q.push(node(U,0));vis[U]=true;
while(Q.size()){
node cur = Q.top();Q.pop();
if(cur.id == 1){
ans = cur.dis;
return ;
}
for(int i=1;i<=U;i++){
if(vis[i])
continue;
dis[i] = min(dis[i] , dis[cur.id] + mp[cur.id][i]);
}
int temp_id;
int temp_dis = INF;
for(int i=1;i<=U;i++){
if(vis[i])
continue;
if(temp_dis > dis[i])
temp_id = i , temp_dis = dis[i];
}
Q.push(node(temp_id,temp_dis));vis[temp_id]=true;
}
}
int main(){
cin>>N>>U;
Init();
for(int i=1;i<=N;i++){
int v,u,w;
cin>>v>>u>>w;
mp[v][u] = mp[u][v] = min(mp[u][v] , w);
}
Dijkstra();
cout<<ans<<endl;
return 0;
}
#include <iostream>
#include <queue>
#include <cstring>
#include <algorithm>
#define INF 0x3f3f3f3f
using namespace std;
const int maxn = 1005;
int N,U;
int mp[maxn][maxn];
bool vis[maxn];
int dis[maxn];
struct node{
int id;
int dis;
node(int id,int dis) : id(id) , dis(dis) {} ;
friend bool operator > (const node & a , const node & b)
{
return a.dis > b.dis;
}
};
priority_queue<node , vector<node> , greater<node> > Q;
int ans;
void Init(){
memset(mp,INF,sizeof(mp));
for(int i=1;i<=U;i++)
mp[i][i] = 0;
memset(dis,INF,sizeof(dis));
memset(vis,0,sizeof(vis));
return ;
}
void Dijkstra(){
dis[U] = 0;
for(int i=1;i<U;i++)
Q.push(node(i,INF));
Q.push(node(U,0));
while(Q.size()){
node cur = Q.top();Q.pop();
if(cur.dis != dis[cur.id])
continue;
vis[cur.id] = true;
if(cur.id == 1){
ans = cur.dis;
return ;
}
for(int i=1;i<=U;i++){
if(vis[i])
continue;
if(dis[i] > dis[cur.id] + mp[cur.id][i])
dis[i] = dis[cur.id] + mp[cur.id][i] , Q.push(node(i , dis[i]));
}
}
}
int main(){
cin>>N>>U;
Init();
for(int i=1;i<=N;i++){
int v,u,w;
cin>>v>>u>>w;
mp[v][u] = mp[u][v] = min(mp[u][v] , w);
}
Dijkstra();
cout<<ans<<endl;
return 0;
}
#include <iostream>
#include <queue>
#include <cstring>
#include <algorithm>
#define INF 0x3f3f3f3f
using namespace std;
const int maxn = 1005;
int N,U;
int mp[maxn][maxn];
bool vis[maxn];
int dis[maxn];
struct node{
int id;
int dis;
node(int id,int dis) : id(id) , dis(dis) {} ;
friend bool operator > (const node & a , const node & b)
{
return a.dis > b.dis;
}
};
priority_queue<node , vector<node> , greater<node> > Q;
int ans;
void Init(){
memset(mp,INF,sizeof(mp));
for(int i=1;i<=U;i++)
mp[i][i] = 0;
memset(dis,INF,sizeof(dis));dis[U]=0;
memset(vis,0,sizeof(vis));
return ;
}
void Dijkstra(){
Q.push(node(U,0));vis[U]=true;
while(Q.size()){
node cur = Q.top();Q.pop();vis[cur.id]=true;
if(cur.id == 1){
ans = cur.dis;
return ;
}
if(cur.dis != dis[cur.id])
continue;
for(int i=1;i<=U;i++){
if(vis[i])
continue;
if(dis[i] > dis[cur.id] + mp[cur.id][i]){
dis[i] = dis[cur.id] + mp[cur.id][i];
Q.push(node(i , dis[i]));
}
}
}
}
int main(){
cin>>N>>U;
Init();
for(int i=1;i<=N;i++){
int v,u,w;
cin>>v>>u>>w;
mp[v][u] = mp[u][v] = min(mp[u][v] , w);
}
Dijkstra();
cout<<ans<<endl;
return 0;
}