水题练Dijkstra的堆优化

http://acm.hdu.edu.cn/showproblem.php?pid=2544

#pragma warning (disable:4786)  
#include<iostream>
#include<vector>
using namespace std;
#define INF 0x3F3F3F3F
struct Edge{
    int v;
    int dis;
};
int n,m;
int dist[102];   //最短路径数组
int visit[102];  //标记节点是否已访问
int dp[102];     //dp[i]=j表示节点i在最小堆中的位置为j 
int vdp[102];    //vdp[i]=j表示在最小堆中位置i的是节点jint heap[102];
int heap[102];   //存储最短路径的最小堆
int heap_num;    //最小堆的size
vector<Edge> edge[102];   //邻接表存储
//自顶向下调整堆
void heap_down(int dis,int v,int num){
	while(num*2<heap_num){
		int left=num*2;
		int right=num*2+1;
		if(dis>heap[left]||(right<heap_num&&dis>heap[right])){
			int min=left;
			if(right<heap_num&&heap[min]>heap[right]){
				min=right;
			}
			int temp=heap[num];
			heap[num]=heap[min];
			heap[min]=temp;
			dp[vdp[num]]=min;
			dp[vdp[min]]=num;
			vdp[num]=vdp[min];
			vdp[min]=v;
			num=min;
		}
        else break;
	}
}
//自底向上调整堆
void heap_up(int dis,int v,int num){
	while(num>1){
		if(heap[num/2]>dis){
			int temp=heap[num];
			heap[num]=heap[num/2];
			heap[num/2]=temp;
			dp[v]=num/2;
			dp[vdp[num/2]]=num;
			vdp[num]=vdp[num/2];			
			vdp[num/2]=v;
			num=num/2;
		}
		else break;
	}
}
//堆的插入
void heap_insert(int dis,int v){
	if(heap_num==1){
		heap[1]=dis;
		dp[v]=1;
		vdp[1]=v;
		heap_num++;
		return;
	}
	heap[heap_num]=dis;
	dp[v]=heap_num;
	vdp[heap_num]=v;
	heap_num++; 
	heap_up(dis,v,heap_num-1);   
}
void heap_update(int dis,int v){
	heap[dp[v]]=dis;
	heap_up(dis,v,dp[v]);
}
//堆的删除
void heap_delete(){
	if(heap_num==2){		
		dp[vdp[1]]=-1;
		heap_num--;
		return;
	}
	heap[1]=heap[heap_num-1];
	dp[vdp[1]]=-1;
	vdp[1]=vdp[heap_num-1];
	dp[vdp[heap_num-1]]=1;
	vdp[heap_num-1]=-1;
	heap_num--;
	heap_down(heap[1],vdp[1],1);	
}
//堆优化的单源最短路算法
void dijkstra(){
	int k,i,j,min;
	dist[1]=0;
	heap_insert(0,1);
	for(i=1;i<=n;i++){
		if(heap_num>1){
			min=heap[1];
			k=vdp[1];
			heap_delete();
		}		
		else break;		
		visit[k]=1;
		for(j=0;j<edge[k].size();j++)
			if(!visit[edge[k][j].v]&&dist[edge[k][j].v]>min+edge[k][j].dis){
				dist[edge[k][j].v]=min+edge[k][j].dis;
				if(dp[edge[k][j].v]!=-1)
					heap_update(dist[edge[k][j].v],edge[k][j].v);
				else heap_insert(dist[edge[k][j].v],edge[k][j].v);
			}
	}
}

int main(){
    while(cin>>n>>m){
        if(!n&&!m)
            break;
		for(int i=0;i<102;i++)
			edge[i].clear();
        for(i=0;i<m;i++){
            int a,b,c;
            cin>>a>>b>>c;
            Edge e;
			e.v=b;e.dis=c;
            edge[a].push_back(e);
            e.v=a;e.dis=c;
            edge[b].push_back(e);
        }
		heap_num=1;
        for(i=1;i<=n;i++){			
			dist[i]=INF;
            visit[i]=0;
			dp[i]=-1;
			vdp[i]=-1;
			heap[i]=-1;
		}
		dijkstra();
        cout<<dist[n]<<endl;
    }
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值