[BZOJ 4144] [AMPPZ2014]Petrol
題目描述
給定一個個點、條邊的帶權無向圖,其中有個點是加油站。
每輛車都有一個油量上限,即每次行走距離不能超過,但在加油站可以補滿。
次詢問,每次給出,表示出發點是,終點是,油量上限為,且保證點和點都是加油站,請回答能否從走到。
輸入輸出格式
輸入格式
第一行包含三個正整數,表示點數、加油站數和邊數。
第二行包含個互不相同的正整數,表示每個加油站。
接下來行,每行三個正整數,表示和之間有一條長度為的雙向邊。
接下來一行包含一個正整數,表示詢問數。
接下來行,每行包含三個正整數,表示一個詢問。
輸出格式
輸出行。第行輸出第個詢問的答案,如果可行,則輸出TAK
NIE
。
輸入輸出樣例
輸入樣例#1:
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
輸出樣例#1:
TAK
TAK
TAK
NIE
解題分析
不難看出非加油站的點都是沒有用的, 我們只關心加油站之間的最短路。
而這個模型又比較特殊, 我們只需要求出加油站的最小生成樹即可。
怎麼快速得到加油站之間的距離呢?有一個很妙的操作:把所有加油站的距離設為, 跑一遍多源最短路並記錄每個點最近的加油站是哪一個, 最後將, 長度為的邊變成, 長度為的邊即可。
注意可能圖中不連通, 倍增預處理的時候要處理完。
程式碼如下:
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cctype>
#include <climits>
#include <algorithm>
#include <cmath>
#include <queue>
#define R register
#define IN inline
#define W while
#define gc getchar()
#define MX 200500
#define ll long long
template <class T>
IN void in(T &x)
{
x = 0; R char c = gc;
for (; !isdigit(c); c = gc);
for (; isdigit(c); c = gc)
x = (x << 1) + (x << 3) + c - 48;
}
template <class T> IN T max(T a, T b) {return a > b ? a : b;}
int dot, line, s, q, cnt;
int head[MX], bel[MX], dis[MX], st[MX], head2[MX], bl[MX], fat[MX][20], mx[MX][20], dep[MX];
bool inq[MX];
std::queue <int> que;
struct INFO {int from, to, len;} dat[MX];
struct Edge {int to, len, nex;} edge[MX << 2];
struct Node {int son[2], fat, val, mx; bool rev;} tree[MX];
IN bool operator < (const INFO &x, const INFO &y) {return x.len > y.len;}
std::priority_queue <INFO> pq;
IN void add(R int from, R int to, R int len) {edge[++cnt] = {to, len, head[from]}, head[from] = cnt;}
IN void add2(R int from, R int to, R int len) {edge[++cnt] = {to, len, head2[from]}, head2[from] = cnt;}
int find(R int now) {return bl[now] == now ? now : bl[now] = find(bl[now]);}
IN void SPFA()
{
std::memset(dis, 63, sizeof(dis));
for (R int i = 1; i <= s; ++i) dis[st[i]] = 0, que.push(st[i]), bel[st[i]] = bl[st[i]] = st[i];
R int now, i;
W (!que.empty())
{
now = que.front(); que.pop();
for (R int i = head[now]; i; i = edge[i].nex)
{
if (dis[edge[i].to] > dis[now] + edge[i].len)
{
dis[edge[i].to] = dis[now] + edge[i].len, bel[edge[i].to] = bel[now];
if (!inq[edge[i].to]) inq[edge[i].to] = true, que.push(edge[i].to);
}
}
inq[now] = false;
}
}
IN void Kruskal()
{
SPFA(); INFO cur; R int bla, blb;
for (R int i = 1; i <= line; ++i)
pq.push({bel[dat[i].from], bel[dat[i].to], dis[dat[i].from] + dis[dat[i].to] + dat[i].len});
int tot = 0;
W (!pq.empty())
{
cur = pq.top(); pq.pop();
bla = find(cur.from), blb = find(cur.to);
if (bla ^ blb)
{
bl[bla] = blb; ++tot;
add2(cur.from, cur.to, cur.len), add2(cur.to, cur.from, cur.len);
}
if (tot == s - 1) break;
}
}
void DFS(R int now, R int val)
{
mx[now][0] = val;
for (R int i = 1; i <= 18; ++i)
{
fat[now][i] = fat[fat[now][i - 1]][i - 1];
if(!fat[now][i]) break;
mx[now][i] = max(mx[now][i - 1], mx[fat[now][i - 1]][i - 1]);
}
for (R int i = head2[now]; i; i = edge[i].nex)
{
if(edge[i].to ^ fat[now][0])
{
fat[edge[i].to][0] = now;
dep[edge[i].to] = dep[now] + 1;
DFS(edge[i].to, edge[i].len);
}
}
}
IN int query(R int x, R int y)
{
if(find(x) ^ find(y)) return INT_MAX;
if(dep[x] < dep[y]) std::swap(x, y);
int del = dep[x] - dep[y], tim = 0, ans = 0;
W (del)
{
if(del & 1) ans = max(ans, mx[x][tim]), x = fat[x][tim];
tim++, del >>= 1;
}
if(x == y) return ans;
for (R int i = 18; ~i; --i) {if(fat[x][i] ^ fat[y][i]) ans = max(ans, max(mx[x][i], mx[y][i])), x = fat[x][i], y = fat[y][i];}
return ans = max(ans, max(mx[x][0], mx[y][0]));
}
int main(void)
{
int x, y, b;
in(dot), in(s), in(line);
for (R int i = 1; i <= s; ++i) in(st[i]);
for (R int i = 1; i <= line; ++i)
{
in(dat[i].from), in(dat[i].to), in(dat[i].len);
add(dat[i].from, dat[i].to, dat[i].len), add(dat[i].to, dat[i].from, dat[i].len);
}
Kruskal(); DFS(st[1], 0); in(q);
W (q--)
{
相關推薦
[BZOJ 4144] [AMPPZ2014]Petrol
題目描述
給定一個nnn個點、mmm條邊的帶權無向圖,其中有sss個點是加油站。
每輛車都有一個油量上限bbb,即每次行走距離不能超過bbb,但在加油站可以補滿。
qqq次詢問,每次給出x,y,bx,y,bx,y,b,表示出發點是xxx,終點是yyy,油量上限
4144: [AMPPZ2014]Petrol (多源最短路+最小生成樹+啟發式合並)
limit make 兩個 不用 gree set emp while include
4144: [AMPPZ2014]Petrol
Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 752 Solved: 298[Sub
[BZOJ 4144] Petrol
gre off pri prior 學會 tro std problem names Link:
BZOJ 4144 傳送門
Solution:
一道不錯的圖論綜合題
因為只詢問關鍵點,因此重點是要求出關鍵點之間的最短路,以最短路建圖
記$nst[i]$為離$i$最近的
【BZOJ4144】[AMPPZ2014]Petrol 最短路+離線+最小生成樹
判斷 eof etc while cpp ont 原來 有一個 style 【BZOJ4144】[AMPPZ2014]Petrol
Description
給定一個n個點、m條邊的帶權無向圖,其中有s個點是加油站。
每輛車都有一個油量上限b,即每次行走距離不能超過
bzoj4144 [AMPPZ2014]Petrol
具體細節 include flag getchar() tor 黑點 strong time bool Description
給定一個 \(n\)個 點、 \(m\) 條邊的帶權無向圖,其中有 \(s\) 個點是加油站。
每輛車都有一個油量上限 \(b\) ,即每次行走距
BZOJ4144 [AMPPZ2014]Petrol 【最短路 + 最小生成樹】
n) IE def zoj 離線 pan www find sizeof 題目鏈接
BZOJ4144
題解
這題好妙啊,,orz
假設我們在一個非加油站點,那麽我們一定是從加油站過來的,我們剩余的油至少要減去這段距離
如果我們在一個非加油站點,如果我們到達不了任意加油站點,
[BZOJ4144][AMPPZ2014]Petrol[多源最短路+MST]
題意
題目連結
分析
假設在 \(a \rightarrow b\) 的最短路徑中出現了一個點 \(x\) 滿足到 \(x\) 最近的點是 \(c\) ,那麼我們完全可以從 \(a\) 直接走到 \(c\),因為 \({dis}_{ax}\geq {dis}_{cx}\) ,而 \(c\) 又是當
bzoj4144: [AMPPZ2014]Petrol 最短路經典問題
連結
Description
給定一個n個點、m條邊的帶權無向圖,其中有s個點是加油站。
每輛車都有一個油量上限b,即每次行走距離不能超過b,但在加油站可以補滿。
q次詢問,每次給出x,y,b,表示出發點是x,終點是y,油量上限為b,且保證x點和y點都是加油站,
BZOJ4144:[AMPPZ2014]Petrol(最短路,最小生成樹)
Description
給定一個n個點、m條邊的帶權無向圖,其中有s個點是加油站。
每輛車都有一個油量上限b,即每次行走距離不能超過b,但在加油站可以補滿。
q次詢問,每次給出x,y,b,表示出發點是x,終點是y,油量上限為b,且保證x點和y點都是加油站,請回答能否從
BZOJ4144: [AMPPZ2014]Petrol(最短路 最小生成樹)
題意
題目連結
Sol
做的時候忘記寫題解了
可以參考這位大爺
#include<bits/stdc++.h>
#define Pair pair<int, int>
#define MP make_pair
#define fi first
#define se secon
Bzoj 4145: [AMPPZ2014]The Prices
Bzoj 4145: [AMPPZ2014]The Prices
狀態壓縮dp
\(f[i][j]\)表示前i個商店 , 狀態為j的最小花費.
考慮什麼東西也不買和買了東西.
買了東西的話,就要到i地.
然後轉移:\(f[i][j] = min(f[i][j] , f[i][j ^ (1 <&
Bzoj 4143: [AMPPZ2014]The Lawyer
getchar sin tchar cstring min har sep else include Bzoj 4143: [AMPPZ2014]The Lawyer
抱歉,水了這一片博客..( ~~ 為了湊出AMPPZ2014.... ~~
顯然記錄最小的右端點,和最大的
Bzoj 4146: [AMPPZ2014]Divisors
Bzoj 4146: [AMPPZ2014]Divisors
暴力剪枝題目
直接列舉倍數.(調和級數
發現過不了的話,就將重複的數合到一起.
時間複雜度\(O(n log n)\)
/*header*/
#include <iostream>
#include <cstdio&g
BZOJ 4152 【AMPPZ2014】船長【建圖優化跑最短路】
兩個排序進行建圖優化:
#include <queue>
#include <cmath>
#include <cstdio>
#include <vector>
#include <cstring>
bzoj - 1007
namespace ans operator using str pac bitset top 技術
1 #include <algorithm>
2 #include <cstring>
3 #include <cstdio>
BZOJ 1411 ZJOI2009 硬幣遊戲
ret dea 遊戲 true 硬幣 air 技術 i++ include 遞推;
1 #include<cstdio>
2 #include<cstring>
3 #include<algorithm>
4 using n
BZOJ 3122 SDOI2013 隨機數生成器
color false std ros == d+ eal eof close 公式就不推了.hzwer上的很清楚.
值得註意的一點是,如果最後答案成0,需要加上mod.否則400ms wa.
1 #include<cstdio>
2 #incl
BZOJ 4827 [Hnoi2017]禮物 ——FFT
最小 sharp scan con 禮物 struct swa 1.0 -i 題目上要求一個循環卷積的最小值,直接破環成鏈然後FFT就可以了。
然後考慮計算的式子,可以分成兩個部分分開計算。
前半部分FFT,後半部分掃一遍。
#include <map>
#i
BZOJ 4569 [Scoi2016]萌萌噠 ——ST表 並查集
oid include long long amp else n) div 每一個 並查集 好題。
ST表又叫做稀疏表,這裏利用了他的性質。
顯然每一個條件可以分成n個條件,顯然過不了。
然後發現有許多狀態是重復的,首先考慮線段樹,沒什麽卵用。
然後ST表,可以每一層表示對
bzoj 1787: [Ahoi2008]Meet 緊急集合
點擊 緊急 ring input ahoi2008 nbsp mage swa problems
1787: [Ahoi2008]Meet 緊急集合
Time Limit: 20 Sec Memory Limit: 162 MBSubmit: 3016 Solve