hdu 2363 Cycling Dijkstra最短路

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

思路:思路其实是和hdu1598类似,先对100个点进行排序,然后枚举最大高度最小高度, 时间复杂度为O(N^2),然后对于每个枚举的最高最低点,对100个点进行筛选,高度在这两者之间的点标记为合法点,然后就是对标记了的结点进行一个Dij, 复杂度为:O(N^2),可以用优先队列优化到O(N*logN),这样就可以求出从源点1到N 的最短路了。时间性能为:O(N^3*logN),N为100 ,1000+MS水过 。。。。。

代码:

/*
Dijkstra  
*/
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<queue>
using namespace std;
const int INF = 0x3f3f3f3f ;
struct Node{
	int h ;
	int num ;
}node[110] ;
int T ,N,M;
int map[110][110] ;
bool with[110];

bool comp(Node n1, Node n2){
	return n1.h < n2.h ;
}
bool vis[110] ;
int dis[110] ;
int min_h , min_d ;
struct Node1{
	Node1(int a, int b)
	:d(a) , num(b) {}
	int d ,num ;
	friend bool operator <(const Node1& n1 , const Node1 &n2){
		if(n1.d == n2.d)	return n1.num < n2.num ;
		return n1.d > n2.d ;
	}
};
priority_queue<Node1> que ;
int Dij(){
	while(!que.empty()) 	que.pop() ;
	for(int i=2;i<=N;i++){
		vis[i] = 0 ;
		if(with[i] == 0)	continue ;
		que.push( Node1( map[1][i] , i)) ;
		dis[i] = map[1][i] ;
	}	
	que.push( Node1(0,1) ) ;
	dis[1] = 0 ;
	for(int i=1;i<=N;i++){
		while(vis[que.top().num]==1)	que.pop() ;
		int min_n = que.top().num ;
		int _min = que.top().d ;
		que.pop() ;
		vis[min_n] = 1 ;
		if(min_n == N)	return _min ;
		for(int j=1;j<=N;j++){
			if(vis[j]==1 || with[j]==0)	continue ;
			if(dis[j] > dis[min_n] + map[min_n][j] ){
				dis[j] = dis[min_n] + map[min_n][j] ;
				que.push( Node1(dis[j] , j) ) ;
			}
		}	
	}
}
void solve(){
	for(int i=1;i<=N;i++){
		for(int j=i;j<=N;j++){
			memset(with ,0 ,sizeof(with) );
			int min_len = node[i].h ;
			int max_len = node[j].h ;
			for(int k=1;k<=N;k++){				//选出满足条件的点
				if(node[k].h >= min_len && node[k].h<=max_len){
					with[ node[k].num ] = 1; 
				}
			}
			if(with[1]==0 || with[N]==0)	continue ;
			Dij() ;
			if(dis[N] != INF){
				if(max_len - min_len < min_h){
					min_h = max_len  - min_len ;
					min_d = dis[N] ;
				}
				else if(max_len - min_len == min_h){
					if(min_d > dis[N])
						min_d = dis[N] ;
				}
			}
		}
	}
	printf("%d %d\n",min_h,min_d);	
}
int main(){
	int a ,b, c; 
	scanf("%d",&T);
	while(T--){
		scanf("%d %d",&N,&M);
		for(int i=1;i<=N;i++){
			scanf("%d",&node[i].h);
			node[i].num = i ;
		}
		for(int i=1;i<=N;i++){
			for(int j=1;j<=N;j++){
				if(i == j)	map[i][j] = 0 ;
				else		map[i][j] = INF ;
			}
		}
		for(int i=1;i<=M;i++){
			scanf("%d %d %d",&a,&b,&c);
			if(map[a][b] > c){
				map[a][b] = map[b][a] = c ;
			}
		}
		sort(node+1, node+1+N , comp);
		min_h = INF ; min_d = INF ;
		solve();	
	}	
	return 0 ;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值