现在的位置: 首页 > 综合 > 正文

poj1062 昂贵的聘礼(dijkstra最短路)

2013年08月09日 ⁄ 综合 ⁄ 共 1561字 ⁄ 字号 评论关闭

       题意说的比较复杂,不过大体是个稍微有点改动的dijkstra算法,为什么说是稍有改动呢,因为多了一个等级的限制,也就是说有向图G中所有的边在不同的等级限制下只能出现一部分,这个限制就是顶点之间的等级(level)之差要小于等于M。

#include <stdio.h>
#include <string.h>
int M;//等级差距
int N;//物品总数

int L[101];//主人等级
int X[101];//替代品总数

int d[101][101];//替代关系的权值
int dcopy[101][101];

int visited[101];

int level_list[101];
int level_list_size;

void init_dcopy(int level){
	int i,j;
	for(i=0;i<=N;i++){
		for(j=0;j<=N;j++){
			if(i==0||j==0){
				dcopy[i][j]=d[i][j];
			}else{
				if(L[i]<level||L[j]<level||L[i]-level>M||L[j]-level>M){
					dcopy[i][j]=-1;
				}else{
					dcopy[i][j]=d[i][j];
				}
			}
		}
	}
}

/**
*目标是找0到1(酋长)的最短路
*/
int dijkstra(){
	memset(visited,0,sizeof(visited));
	
	int step=N-1;
	int i;
	int min_v;
	int min_i;
	while(step--){//最多进行N-1次
		min_v=d[0][1]+1;
		for(i=1;i<=N;i++){//找到未访问的权值最小的顶点
			if(!visited[i]){
				if(dcopy[0][i]<min_v){
					min_i=i;
					min_v=dcopy[0][i];
				}
			}
		}

		if(min_i==1){//找到到1(酋长)的最短路了,不用继续了
			return min_v;
		}
		
		visited[min_i]=1;
		
		for(i=1;i<=N;i++){
			if(visited[i]){//用找到的顶点松弛未访问的顶点
				continue;
			}
			if(dcopy[min_i][i]!=-1&&min_v+dcopy[min_i][i]<dcopy[0][i]){//松弛
				dcopy[0][i]=min_v+dcopy[min_i][i];
			}
		}
	}
	return dcopy[0][1];
	
}

int findlevel(int level){
	int i;
	for(i=0;i<level_list_size;i++){
		if(level_list[i]==level){
			return 1;
		}
	}
	return 0;
}



int main(void){
	memset(d,-1,sizeof(d));
	level_list_size=0;

	scanf("%d %d",&M,&N);
	int i,j;
	int P,T,V;
	for(i=1;i<=N;i++){
		scanf("%d %d %d",&P,&L[i],&X[i]);
		d[0][i]=P;
		d[i][0]=P;
		for(j=0;j<X[i];j++){
			scanf("%d %d",&T,&V);
			d[T][i]=V;//这地方是有向图,刚开始当成无向图了,WA的蛋疼菊紧.....
		}
	}
	
	int min_cost=d[0][1];
	int cost;
	for(i=1;i<=N;i++){
		if(!findlevel(L[i])){
			level_list[level_list_size++]=L[i];
			init_dcopy(L[i]);
			cost=dijkstra();
			if(cost<min_cost){
				min_cost=cost;
			}
		}
	}
	
	printf("%d\n",min_cost);
	return 0;
}

       

抱歉!评论已关闭.