标签:io os ar for sp 2014 art on amp
题意:求期望红绿灯时间下,途径若干加油站,经过最多若干个红绿灯,起点与终点的最短路。
思路:每个有红绿灯的节点通过时间怎么算呢?事实上t=red*red/2/(red+green),然后把这个时间附加到节点的出边上。
随后我们建立分层图,第i层表示经过了i个红绿灯时,从源点到该点的最短路径长度。
如果没有油量限制,那么我们直接跑最短路就行了。
注意到加油站很少,于是我们枚举以每个加油站为起点,向其他加油站经过若干个红绿灯的最短路径。若此长度不大于最大油量,那么可以直接转移。
我们用上述信息构造新图,依旧是分层图,可是每一层仅有50个点,且没有油量限制。
一次最短路出解。
Code:
#include <map>
#include <queue>
#include <string>
#include <cstdio>
#include <cctype>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef double f2;
#define _abs(x) ((x)>0?(x):-(x))
#define N 10010
int n, m, dep, lim, cost;
bool isGas[N];
f2 length[N];
map<string, int> M;
int id, S, T;
int Point_id, lab[11][N];
struct Node {
int lab;
f2 dis;
Node(int _lab = 0, f2 _dis = 0):lab(_lab),dis(_dis){}
bool operator < (const Node &B) const {
return dis < B.dis;
}
};
void swap(Node &x, Node &y) {
Node tmp = x;
x = y;
y = tmp;
}
struct Heap {
Node a[110010];
int top;
Heap():top(0){}
void up(int x) {
for(; x != 1; x >>= 1)
if (a[x] < a[x >> 1])
swap(a[x], a[x >> 1]);
else
break;
}
void down(int x) {
int son;
for(; (x << 1) <= top; ) {
son=(((x<<1)==top)||(a[x<<1]<a[(x<<1)|1]))?(x<<1):((x<<1)|1);
if (a[son] < a[x]) {
swap(a[son], a[x]);
x = son;
}
else
break;
}
}
void insert(const Node &x) {
a[++top] = x;
up(top);
}
Node Min() {
return a[1];
}
void pop() {
a[1] = a[top--];
down(1);
}
}H;
queue<int> q;
struct Graph {
int head[110010], next[450010], end[450010], ind;
f2 len[450010], dis[110010];
bool inpath[110010];
void reset() {
ind = 0;
memset(head, -1, sizeof head);
}
void addedge(int a, int b, f2 _len) {
int q = ind++;
end[q] = b;
next[q] = head[a];
head[a] = q;
len[q] = _len;
}
void spfa(int S) {
register int i, j;
for(i = 1; i <= Point_id; ++i)
dis[i] = 1e10;
dis[S] = 0;
memset(inpath, 0, sizeof(inpath));
H.top = 0, H.insert(Node(S, 0));
Node tmp;
while(H.top) {
tmp = Node(0, 0);
while(H.top) {
tmp = H.Min();
H.pop();
if (!inpath[tmp.lab] && _abs(tmp.dis - dis[tmp.lab]) <= 1e-6)
break;
}
if (tmp.lab == 0)
break;
inpath[tmp.lab] = 1;
for(j = head[tmp.lab]; j != -1; j = next[j])
if (dis[end[j]] > dis[tmp.lab] + len[j]) {
dis[end[j]] = dis[tmp.lab] + len[j];
H.insert(Node(end[j], dis[end[j]]));
}
}
}
}G1, G2;
void Getaddedge(int a, int b, int len) {
int j;
if (_abs(length[b]) > 1e-7)
for(j = 0; j < dep; ++j)
G1.addedge(lab[j][a], lab[j + 1][b], len + length[b]);
else
for(j = 0; j <= dep; ++j)
G1.addedge(lab[j][a], lab[j][b], len);
}
int Gases[101], top;
int main() {
scanf("%d%d%d%d%d", &n, &m, &dep, &lim, &cost);
register int i, j, k, p;
for(i = 0; i <= dep; ++i)
for(j = 1; j <= n; ++j)
lab[i][j] = ++Point_id;
string s, s1, s2;
int red, green, num;
for(i = 1; i <= n; ++i) {
cin >> s >> red >> green;
num = M[s];
if (!num)
M[s] = num = ++id;
if (s == "start")
S = num;
else if (s == "end")
T = num;
else if (s.find("gas") != string::npos)
isGas[num] = 1;
if (red)
length[num] = red * red / ((f2)2 * (red + green));
}
G1.reset();
G2.reset();
int a, b, len;
for(i = 1; i <= m; ++i) {
cin >> s1 >> s2 >> s >> len;
a = M[s1], b = M[s2];
Getaddedge(a, b, len);
Getaddedge(b, a, len);
}
isGas[S] = isGas[T] = 1;
for(i = 1; i <= n; ++i)
if (isGas[i])
Gases[++top] = i;
for(i = 1; i <= top; ++i) {
G1.spfa(lab[0][Gases[i]]);
for(j = 1; j <= top; ++j) {
if (i == j)
continue;
f2 add = (Gases[j] != S && Gases[j] != T) ? cost : 0;
for(k = 0; k <= dep; ++k)
if (G1.dis[lab[k][Gases[j]]] <= lim)
for(p = 0; p + k <= dep; ++p)
G2.addedge(lab[p][Gases[i]], lab[p + k][Gases[j]], G1.dis[lab[k][Gases[j]]] + add);
}
}
G2.spfa(lab[0][S]);
f2 res = 1e10;
for(i = 0; i <= dep; ++i)
res = min(res, G2.dis[lab[i][T]]);
printf("%.3lf", res);
return 0;
}标签:io os ar for sp 2014 art on amp
原文地址:http://blog.csdn.net/wyfcyx_forever/article/details/40181251