#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;
}
URAL 1980 Road to Investor (二分 + SPFA)
最新推荐文章于 2017-10-14 10:59:31 发布