URAL 1980 Road to Investor (二分 + SPFA)

#include <stdio.h>
#define MAX_CROSSES 10000
#define MAX_ROADS 10000
#define PRECISION 1e-7
#define FABS(x) ( (x) > 0 ? (x) : - (x) )
#define INF_TIME 1e6

int numOfCrosses, numOfRoads;
typedef struct Road{
	int road;
	int adjaCross;
	double speedLimit;
	double longOfRoad;
	int next;
}Road;
Road arrayOfRoads[MAX_ROADS * 2 + 1];//当邻接链表用
int RoadNum;
int RoadNumOfHead[MAX_CROSSES + 1];
double hoursLeft;
double overSpeeding, minOverSpeeding, maxOverSpeeding;
double timeOfArrivingCross[MAX_CROSSES + 1];
int isInQueue[MAX_CROSSES + 1];
int preCross[MAX_CROSSES + 1];
int roadPassed[MAX_CROSSES + 1];//记录经过的路,用作输出
int queue[MAX_CROSSES + 1];
int head, tail;
int stack[MAX_CROSSES + 1];
int top;

void addRoad(int road, int head, int adjaCross, double speedLimit, double longOfRoad){
	Road newRoad;
	newRoad.road = road;
	newRoad.adjaCross = adjaCross;
	newRoad.speedLimit = speedLimit;
	newRoad.longOfRoad = longOfRoad;
	newRoad.next = RoadNumOfHead[head];
	RoadNum++;
	arrayOfRoads[RoadNum] = newRoad;
	RoadNumOfHead[head] = RoadNum;	
}

double getMinTimeOfArrivingInvestorBySPFA(double overSpeeding){
	int cross;
	for (cross = 1; cross <= numOfCrosses; cross++){
		timeOfArrivingCross[cross] = INF_TIME;
		isInQueue[cross] = preCross[cross] = 0;
	}
	//别忘了初始化起点的到达时间timeOfArrivingCross[1]
	timeOfArrivingCross[1] = 0;
	head = tail = 1;
	queue[tail++] = 1;
	isInQueue[1] = 1;

	while (head < tail){
		int crossPoped = queue[head++];
		isInQueue[crossPoped] = 0;
		int indexOfRoad;
		for (indexOfRoad = RoadNumOfHead[crossPoped]; indexOfRoad != 0; indexOfRoad = arrayOfRoads[indexOfRoad].next){
			Road tempRoad = arrayOfRoads[indexOfRoad];
			double time = tempRoad.longOfRoad / (tempRoad.speedLimit + overSpeeding);
			int adjaCross = tempRoad.adjaCross;
			if (timeOfArrivingCross[crossPoped] + time < timeOfArrivingCross[adjaCross]){
				timeOfArrivingCross[adjaCross] = timeOfArrivingCross[crossPoped] + time;
				preCross[adjaCross] = crossPoped;
				roadPassed[adjaCross] = tempRoad.road;
				if (isInQueue[adjaCross] == 0){
					queue[tail++] = adjaCross;
					isInQueue[adjaCross] = 1;
				}
			}
		}	
	}
	return timeOfArrivingCross[numOfCrosses];
}

int main(){
	
	scanf("%d %d", &numOfCrosses, &numOfRoads);
	int road;
	for (road = 1; road <= numOfRoads; road++){
		int oneCross, anotherCross;
		double longOfRoad, speedLimit;
		//注意double输入得用%lf
		scanf("%d %d %lf %lf", &oneCross, &anotherCross, &speedLimit, &longOfRoad);
		addRoad(road, oneCross, anotherCross, speedLimit, longOfRoad);
		addRoad(road, anotherCross, oneCross, speedLimit, longOfRoad);
	}
	scanf("%lf", &hoursLeft);

	maxOverSpeeding = 1e7;
	//因为确定超速多少之后才能求出到达目的地的最小时间,所以要二分答案
	while (FABS(maxOverSpeeding - minOverSpeeding) > PRECISION){
		overSpeeding = (minOverSpeeding + maxOverSpeeding) / 2;
		if (getMinTimeOfArrivingInvestorBySPFA(overSpeeding) <= hoursLeft)
			//及时到达,超速可以减小
			maxOverSpeeding = overSpeeding;
		else
			//迟到,超速要增大
			minOverSpeeding = overSpeeding;
	}

	int cross = numOfCrosses;
	while (preCross[cross] != 0){
		stack[top++] = roadPassed[cross];
		cross = preCross[cross];
	}

	//注意输出格式
	printf("%.6f %d\n", overSpeeding, top);
	for (top--; top >= 0; top--)
		printf("%d%c", stack[top], top == 0 ? '\n' : ' ');

	return 0;
}

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值