题意:一个人要从家到学校,步行速度10km/h,图上有地铁40km/h,地铁有不同线路,每个线路上的地铁可以互通,相邻两站之间地铁以直线运行,不同地铁线路之间不能直接通过地铁乘坐到达,但不同地点间可以直接步行,按直线走。给出家、学校、各地铁站台的坐标(单位 m),问从家到学校最短需要花费多少时间(min)?
单位有点坑。。。。。。地铁线不一定是直的一站一站的建,剩余的全部步行建图
链接:poj 2502
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <set>
#include <map>
#include <stack>
#include <queue>
#define inf 0x3f3f3f3f
using namespace std;
const int maxn = 1005;
const int maxm = 100500;
int n = maxn, m, s, t; //n为点数 s为源点
int head[maxn]; //head[from]表示以head为出发点的邻接表表头在数组es中的位置,开始时所有元素初始化为-1
double d[maxn]; //储存到源节点的距离,在init()中初始化
bool vis[maxn]; //是否访问过
int nodep; //在邻接表和指向表头的head数组中定位用的记录指针,开始时初始化为0
int pre[maxn];
struct node {
int num;
double dis;
node (int a = 0, int b = 0) : num(a), dis(b) {}
friend bool operator <(node a, node b) {
return a.dis > b.dis;
}
};
struct node1 {
int num;
int dis;
node1 (int a = 0, int b = 0) : num(a), dis(b) {}
friend bool operator <(node1 a, node1 b) {
if(a.dis == b.dis) return a.num < b.num;
return a.dis < b.dis;
}
};
struct edge {
int v, next;
double w;
}es[maxm];
void init() {
for(int i = 0; i < maxn; i++) {
d[i] = inf;
vis[i] = false;
head[i] = -1;
pre[i] = -1;
}
nodep = 0;
}
void addedge(int from, int to, double weight)
{
es[nodep].v = to;
es[nodep].w = weight;
es[nodep].next = head[from];
head[from] = nodep++;
}
void dijkstra()
{
priority_queue<node> pq;
d[s] = 0; //s为源点
pq.push(node(s, 0));
while(!pq.empty()) {
node num = pq.top();
pq.pop();
int u = num.num;
if(vis[u]) continue;
vis[u] = 1;
//遍历邻接表
for(int i = head[u]; i != -1; i = es[i].next) { //在es中,相同from出发指向的顶点为从head[from]开始的一项,逐项使用next寻找下去,直到找到第一个被输
//入的项,其next值为-1
int v = es[i].v;
if(!vis[v] && d[v] > d[u] + es[i].w) { //松弛(RELAX)操作
d[v] = d[u] + es[i].w;
//pre[v] = u;
pq.push(node(v, d[v]));
}
}
}
}
void putpath() {
stack<int> path;
int now = t;
while(1) {
path.push(now);
if(now == s) {
break;
}
now = pre[now];
}
while(!path.empty()) {
now = path.top();
path.pop();
printf("%d\n", now);
}
}
int p[maxn], x[maxn], y[maxn];
double cal(int a,int b){
return sqrt(1.0 * (x[a] - x[b]) * (x[a] - x[b]) + 1.0 * (y[a] - y[b]) * (y[a] - y[b]));
}
int v[maxn][maxn] = {0};
int main()
{
init();
int T, kcase = 0;
int cnt = 0;
cin >> x[1] >> y[1] >> x[2] >> y[2];
map<node1, int> mp;
mp[node1(x[1], y[1])] = ++cnt;
mp[node1(x[2], y[2])] = ++cnt;
int x1, y1;
int c = 0;
while(scanf("%d %d", &x1, &y1) != EOF) {
if(x1 == -1 && y1 == -1) {
for(int i = 2; i <= c; i++) {
int j = i - 1;
addedge(p[i], p[j], cal(p[i], p[j]) / 40.0 * 3.6);
addedge(p[j], p[i], cal(p[i], p[j]) / 40.0 * 3.6);
v[p[i]][p[j]] = v[p[j]][p[i]] = 1;
}
c = 0;
}
else {
node1 tmp(x1, y1);
if(mp[tmp]) p[++c] = mp[tmp];
else {
p[++c] = mp[tmp] = ++cnt;
x[cnt] = x1;
y[cnt] = y1;
}
}
}
for(int i = 1; i <= cnt; i++) {
for(int j = i + 1; j <= cnt; j++) {
if(!v[i][j]) {
addedge(i, j, cal(i, j) / 10.0 * 3.6);
addedge(j, i, cal(i, j) / 10.0 * 3.6);
}
}
}
s = 1, n = cnt;
dijkstra();
printf("%d\n",(int)(d[2] / 60.0 + 0.5));
return 0;
}
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <set>
#include <map>
#include <stack>
#include <queue>
#define inf 0x3f3f3f3f
using namespace std;
const int maxn = 1005;
const int maxm = 100500;
int n, m, s, t; //n为点数 s为源点
int head[maxn]; //head[from]表示以head为出发点的邻接表表头在数组es中的位置,开始时所有元素初始化为-1
double d[maxn]; //储存到源节点的距离,在Spfa()中初始化
int cnt[maxn];
bool inq[maxn]; //这里inq作inqueue解释会更好,出于习惯使用了inq来命名,在Spfa()中初始化
int nodep; //在邻接表和指向表头的head数组中定位用的记录指针,开始时初始化为0
int pre[maxn];
struct node1 {
int num;
int dis;
node1 (int a = 0, int b = 0) : num(a), dis(b) {}
friend bool operator <(node1 a, node1 b) {
if(a.dis == b.dis) return a.num < b.num;
return a.dis < b.dis;
}
};
struct node {
int v, next;
double w;
}es[maxm];
void init() {
for(int i = 1; i < maxn; i++) {
d[i] = inf;
inq[i] = false;
cnt[i] = 0;
head[i] = -1;
pre[i] = -1;
}
nodep = 0;
}
void addedge(int from, int to, double weight)
{
es[nodep].v = to;
es[nodep].w = weight;
es[nodep].next = head[from];
head[from] = nodep++;
}
bool spfa()
{
queue<int> que;
d[s] = 0; //s为源点
inq[s] = 1;
que.push(s);
while(!que.empty()) {
int u = que.front();
que.pop();
inq[u] = false; //从queue中退出
//遍历邻接表
for(int i = head[u]; i != -1; i = es[i].next) { //在es中,相同from出发指向的顶点为从head[from]开始的一项,逐项使用next寻找下去,直到找到第一个被输
//入的项,其next值为-1
int v = es[i].v;
if(d[v] > d[u] + es[i].w) { //松弛(RELAX)操作
d[v] = d[u] + es[i].w;
//pre[v] = u;
if(!inq[v]) { //若被搜索到的节点不在队列que中,则把to加入到队列中去
inq[v] = true;
que.push(v);
if(++cnt[v] > n) {
return false;
}
}
}
}
}
return true;
}
void putpath() {
stack<int> path;
int now = t;
while(1) {
path.push(now);
if(now == s) {
break;
}
now = pre[now];
}
while(!path.empty()) {
now = path.top();
path.pop();
printf("%d\n", now);
}
}
int p[maxn], x[maxn], y[maxn];
double cal(int a, int b) {
return sqrt(1.0 * (x[a] - x[b]) * (x[a] - x[b]) + 1.0 * (y[a] - y[b]) * (y[a] - y[b]));
}
int v[maxn][maxn] = {0};
int main()
{
init();
int T, kcase = 0;
int cnt = 0;
cin >> x[1] >> y[1] >> x[2] >> y[2];
map<node1, int> mp;
mp[node1(x[1], y[1])] = ++cnt;
mp[node1(x[2], y[2])] = ++cnt;
int x1, y1;
int c = 0;
while(scanf("%d %d", &x1, &y1) != EOF) {
if(x1 == -1 && y1 == -1) {
for(int i = 2; i <= c; i++) {
int j = i - 1;
addedge(p[i], p[j], cal(p[i], p[j]) / 40.0 * 3.6);
addedge(p[j], p[i], cal(p[i], p[j]) / 40.0 * 3.6);
v[p[i]][p[j]] = v[p[j]][p[i]] = 1;
}
c = 0;
}
else {
node1 tmp(x1, y1);
if(mp[tmp]) p[++c] = mp[tmp];
else {
p[++c] = mp[tmp] = ++cnt;
x[cnt] = x1;
y[cnt] = y1;
}
}
}
for(int i = 1; i <= cnt; i++) {
for(int j = i + 1; j <= cnt; j++) {
if(!v[i][j]) {
addedge(i, j, cal(i, j) / 10.0 * 3.6);
addedge(j, i, cal(i, j) / 10.0 * 3.6);
}
}
}
s = 1, n = cnt;
if(spfa());
printf("%d\n", (int)(d[2] / 60.0 + 0.5));
}