写在前面的话:
接下来是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 ;
}