Subway POJ - 2502
思路:很裸的最短路,难就难在建图,用邻接表建图时要把边开大点,别看数据范围仅仅200,开了1w都RE,索性开到了10W就AC了
具体代码如下
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<cmath>
using namespace std;
const int N = 510, M = 100010;
int h[N], e[M], ne[M], idx;
int cnt = 2;
int x1, y1, x2, y2;
double w[M];
double dis[N];
bool st[N];
struct Node{
int x, y;
}node[N];
void add(int a, int b, double c){
e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx++;
}
double getD(int x1, int y1, int x2, int y2, int t){
double x = x1 - x2;
double y = y1 - y2;
return sqrt(x*x + y*y) /t / 1000 * 60;
}
bool cmp(double a, double b) {
if (a - b > 1e-4) return true;
return false;
}
void spfa(){
for(int i=0; i<cnt; ++i) dis[i] = 1e18;
dis[0] = 0;
queue<int> q;
q.push(0);
while(q.size()){
int t = q.front();
q.pop();
st[t] = false;
for(int i=h[t]; i!=-1; i=ne[i]){
int j = e[i];
if(cmp(dis[j], dis[t] + w[i])){
dis[j] = dis[t] + w[i];
if(!st[j]){
st[j] = true;
q.push(j);
}
}
}
}
}
int main(){
memset(h, -1, sizeof h);
scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
add(0, 1, getD(x1, y1, x2, y2, 10));//我们把0当做起点,1当做终点
add(1, 0, getD(x1, y1, x2, y2, 10));
int x, y;
while(~scanf("%d%d", &node[cnt].x, &node[cnt].y)){
x = node[cnt].x, y = node[cnt].y;
add(0, cnt, getD(x, y, x1, y1, 10));
add(cnt, 1, getD(x, y, x2, y2, 10));
cnt++;
while(scanf("%d%d", &node[cnt].x, &node[cnt].y)){
if(node[cnt].x == -1) break;
add(0, cnt, getD(node[cnt].x, node[cnt].y, x1, y1, 10));
add(cnt, 1, getD(node[cnt].x, node[cnt].y, x2, y2, 10));
add(cnt-1, cnt, getD(node[cnt].x, node[cnt].y, node[cnt-1].x, node[cnt-1].y, 40));
add(cnt, cnt-1, getD(node[cnt].x, node[cnt].y, node[cnt-1].x, node[cnt-1].y, 40));
cnt++;
}
}
for(int i=2; i<cnt; ++i)
for(int j=i+1; j<cnt; ++j){
add(i, j, getD(node[i].x, node[i].y, node[j].x, node[j].y, 10));
add(j, i, getD(node[i].x, node[i].y, node[j].x, node[j].y, 10));
}//每两个地铁站都可以走过去
spfa();
printf("%d\n", (int)(dis[1] + 0.5));//这里要四舍五入
return 0;
}