## 4144: [AMPPZ2014]Petrol

Time Limit: 10 Sec  Memory Limit: 256 MB
Submit: 457  Solved: 170
[Submit][Status][Discuss]

## Description

q次询问，每次给出x,y,b，表示出发点是x，终点是y，油量上限为b，且保证x点和y点都是加油站，请回答能否从x走到y。

6 4 5
1 5 2 6
1 3 1
2 3 2
3 4 3
4 5 5
6 4 5
4
1 2 4
2 6 9
1 5 9
6 5 8

TAK
TAK
TAK
NIE

## Source

[Submit][Status][Discuss]

# 代码

 #include <cmath>
#include <queue>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

#define N 500005
#define inf 0x3f3f3f3f

int n, m, s, c[N];

struct edge
{
int x, y, w;

edge(void) {};
edge(int _x, int _y, int _w) :
x(_x), y(_y), w(_w) {};

friend bool operator < (const edge &a, const edge &b)
{
return a.w < b.w;
}
};

struct step
{
int id, dis;

step(void) {};
step(int a, int b) :
id(a), dis(b) {};

friend bool operator < (const step &a, const step &b)
{
return a.dis > b.dis;
}
};

namespace kirito
{
edge e[N]; ;

int hd[N], to[N], vl[N], nt[N], tot;

void addEdge(int x, int y, int w)
{
nt[tot] = hd[x]; to[tot] = y; vl[tot] = w; hd[x] = tot++;
nt[tot] = hd[y]; to[tot] = x; vl[tot] = w; hd[y] = tot++;
}

int dis[N], from[N];

priority_queue<step> pq;
}

namespace masiro
{
edge e[N]; ;

void pushEdge(int x, int y, int w)
{
e[++edge_cnt] = edge(x, y, w);
}

int hd[N], to[N], vl[N], nt[N], tot;

void addEdge(int x, int y, int w)
{
nt[tot] = hd[x]; to[tot] = y; vl[tot] = w; hd[x] = tot++;
nt[tot] = hd[y]; to[tot] = x; vl[tot] = w; hd[y] = tot++;
}

int fa[N];

int find(int u)
{
return fa[u] == u ? u : fa[u] = find(fa[u]);
}

int root;

], mex[N][];

void predfs(int u, int f)
{
; i < ; ++i)
{
fat[u][i] = fat[fat[u][i - ]][i - ];
mex[u][i] = max(mex[u][i - ], mex[fat[u][i - ]][i - ]);
}

for (int i = hd[u]; ~i; i = nt[i])
if (to[i] != f)
{
dep[to[i]] = dep[u] + ;
mex[to[i]][] = vl[i];
fat[to[i]][] = u;
predfs(to[i], u);
}
}
}

void prework1(void)
{
using namespace kirito;

memset(dis, inf, sizeof(dis));

; i <= s; ++i)
{
dis[c[i]] = ;
from[c[i]] = c[i];
pq.push(step(c[i], ));
}

while (!pq.empty())
{
step top = pq.top(); pq.pop();

if (dis[top.id] != top.dis)
continue;

for (int i = hd[top.id]; ~i; i = nt[i])
if (dis[to[i]] > vl[i] + top.dis)
{
from[to[i]] = from[top.id];
dis[to[i]] = vl[i] + top.dis;
pq.push(step(to[i], dis[to[i]]));
}
}

; i <= m; ++i)
if (from[e[i].x] ^ from[e[i].y])
masiro::pushEdge(from[e[i].x], from[e[i].y], dis[e[i].x] + dis[e[i].y] + e[i].w);
}

void prework2(void)
{
using namespace masiro;

sort(e + , e +  + edge_cnt);

; i <= n; ++i)
fa[i] = i;

; i <= edge_cnt; ++i)
{
int fx = find(e[i].x);
int fy = find(e[i].y);

if (fx ^ fy)
{
fa[fx] = fy;
}
}

root = n + ;

; i <= s; ++i)
if (find(c[i]) == c[i])

dep[root] = ;
fat[root][] = root;
memset(mex, , sizeof(mex));

predfs(root, -);
}

int lca(int x, int y)
{
using namespace masiro;

;

if (dep[x] < dep[y])
swap(x, y);

; i >= ; --i)
if (dep[fat[x][i]] >= dep[y])
{
res = max(res, mex[x][i]);
x = fat[x][i];
}

if (x == y)
return res;

; i >= ; --i)
if (fat[x][i] != fat[y][i])
{
res = max(res, mex[x][i]);
res = max(res, mex[y][i]);
x = fat[x][i];
y = fat[y][i];
}

res = max(res, mex[x][]);
res = max(res, mex[y][]);

return res;
}

signed main(void)
{
scanf("%d%d%d", &n, &s, &m);

; i <= s; ++i)
scanf("%d", c + i);

memset(kirito::hd, -, sizeof(kirito::hd));
memset(masiro::hd, -, sizeof(masiro::hd));

; i <= m; ++i)
{
int x, y, w; scanf("%d%d%d", &x, &y, &w);

kirito::e[i] = edge(x, y, w);
}

prework1();
prework2();

int q; scanf("%d", &q);

; i <= q; ++i)
{
int x, y, w; scanf("%d%d%d", &x, &y, &w);

int maxCost = lca(x, y);

if (w >= maxCost)
puts("TAK");
else
puts("NIE");
}
}

BZOJ_4144.cpp

@Author: YouSiki

## BZOJ 4144: [AMPPZ2014]Petrol的更多相关文章

1. 【BZOJ】4144: [AMPPZ2014]Petrol

题意 给定一个$$n$$个点.$$m$$条边的带权无向图,其中有$$s$$个点是加油站.每辆车都有一个油量上限$$b$$,即每次行走距离不能超过$$b$$,但在加油站可以补满.$$q$$次询问,每次给 ...

2. 循环队列+堆优化dijkstra最短路 BZOJ 4152: [AMPPZ2014]The Captain

循环队列基础知识 1.循环队列需要几个参数来确定 循环队列需要2个参数,front和rear 2.循环队列各个参数的含义 (1)队列初始化时,front和rear值都为零: (2)当队列不为空时,fr ...

3. BZOJ 4152: [AMPPZ2014]The Captain( 最短路 )

先按x排序, 然后只有相邻节点的边才有用, 我们连起来, 再按y排序做相同操作...然后就dijkstra ---------------------------------------------- ...

4. BZOJ 4143: [AMPPZ2014]The Lawyer( sort )

水题... 排序搞出每天的会议有哪些, 然后再按照会议的开始时间和结束时间排序, 最晚开始的和最早结束的会议不是同一场而且最晚开始的时间>最早结束的会议就有可能方案 -------------- ...

5. BZOJ 4145: [AMPPZ2014]The Prices( 状压dp + 01背包 )

我自己只能想出O( n*3^m )的做法....肯定会T O( nm*2^m )做法: dp( x, s ) 表示考虑了前 x 个商店, 已买的东西的集合为s. 考虑转移 : 先假设我们到第x个商店去 ...

6. BZOJ 4146 [AMPPZ2014] Divisors 解题报告