CF1253F Cheap Robot
CF1253F Cheap Robot
題意:
給你一張 N 個點的帶權無向連通圖,其中結點 1,2,…,k 為充電中心。
一個機器人在圖中行走,假設機器人的電池容量為 c,則任何時刻,機器人的電量 x 都必須滿足 c0≤x≤c。如果機器人沿著一條邊權為 w 的邊從結點 i 走到結點 j,它的電量會減少 w。機器人可以在到達某個充電中心時把電量充滿。
現在有 q 個詢問,每次詢問機器人要從 a 點到達 b 點,電池容量至少為多少,各個詢問相互獨立。保證 a 點和 b 點都是充電中心。
題解:
我和隊友討論這個題,討論的大差不差,但是有個錯誤。我們一開始認為點a到點b的距離,直接跑最小生成樹就可以,但其實并不是,我們忽略了充電中心的作用,比如從3到1,路線為3→9→8→7→2→7→6→5→4→1,到7時并沒有直接前往6,而是先到2充滿電,然后在去6,這樣相當于及時充電。
也就是我們可以通過走向最近的充電中心來補充能量,這樣可以優化電池容量,所以我們需要求出任意一個點到離他最近的充電站的距離
這怎么求?多源最短路,沒必要,我們可以建一個超級源點,連向所有充電站,邊權為0,然后再新圖上跑一個最短路,求出所有點到離他最近的充電站的距離
現在得到dis[i]:表示距離點i最近的充電站的距離
怎么用呢?如下
對于一個可以完成的路徑(不會在半路因為能量不足而無法完成)
我們設當前走到點i,剩余電量為x,一定會有x>=disix>=dis_{i}x>=disi?(題目保證終點是充電站,且中途可以充電,如果x<dis_{i}就無法走到終點了)
設電容量為c,有c>=x>=disic>=x>=dis_{i}c>=x>=disi?,c相當于上界
因為走到i點至少要消耗disidis_{i}disi?的電(因為距離i最近的充電站才dis_{i},不可能總消耗比dis_{i}還小),所以有:c?disi>=x>=disic-dis_{i}>=x>=dis_{i}c?disi?>=x>=disi?
設下一個點是j,且邊權為wijwijwij,有:c?disj>=x?wi,j>=disjc-dis_{j}>=x-w_{i,j}>=dis_{j}c?disj?>=x?wi,j?>=disj?,道理同上(注意這個式子里的下標是j)
現在我們合并兩個式子,就可以得到關于點i到點j的路徑信息
有:x?wi,j>=disjx-w_{i,j}>=dis_{j}x?wi,j?>=disj?,我們用c來代替x,因為我們想要的是與c相關的式子,得到:
disj<=c?disi?wi,jdis_{j}<=c-dis_{i}-w_{i,j}disj?<=c?disi??wi,j?
整理:
c>=disi+disj+wi,jc>=dis_{i}+dis_{j}+w_{i,j}c>=disi?+disj?+wi,j?
這個式子的含義不就是從點i到點j所需要的最小電池容量為disi+disj+wi,jdis_{i}+dis_{j}+w_{i,j}disi?+disj?+wi,j?,也就是我們求出了原圖中任意兩個相鄰點所需要的電池容量。
上述推到過程建議仔細閱讀,慢慢體會,很妙
現在每次詢問一個起點 a 到 b 的最小電池容量,就是找一條從 a 點到 b 點的路徑,使得這個路徑上的最大值最小
這個路徑一定是在最小生成樹上的,這是最小生成樹經常解決的問題。因為最小生成樹加邊是從小到大,且保證圖聯通的情況下
我們構造最小生成樹,然后問題就變成求a到b路徑上的最大值,可以用LCA+倍增來求
這是一個綜合性很強且考察代碼能力的題,值得一刷
代碼:
// Problem: F. Cheap Robot // Contest: Codeforces - Codeforces Round #600 (Div. 2) // URL: https://codeforces.com/contest/1253/problem/F // Memory Limit: 512 MB // Time Limit: 3000 ms // // Powered by CP Editor (https://cpeditor.org)//#pragma GCC target("avx") //#pragma GCC optimize(2) //#pragma GCC optimize(3) //#pragma GCC optimize("Ofast") // created by myq #include <algorithm> #include <cctype> #include <climits> #include <cmath> #include <cstdio> #include <cstdlib> #include <cstring> #include <iostream> #include <list> #include <map> #include <queue> #include <set> #include <sstream> #include <stack> #include <string> #include <unordered_map> #include <unordered_set> #include <vector> using namespace std; typedef long long ll; #define x first #define y second typedef pair<ll,ll> pii; const int N= 400010; const int mod= 998244353; inline int read() {int res= 0;int f= 1;char c= getchar();while (c > '9' || c < '0') {if (c == '-')f= -1;c= getchar();}while (c >= '0' && c <= '9') {res= (res << 3) + (res << 1) + c - '0';c= getchar();}return res; } struct node {int a;int b;ll c;bool operator<(const node& w) const{return c < w.c;} } q[N]; int p[N]; vector<pii> v[N]; int idx; int n, m, k, _; int newcnt; int val[N]; ll dist[N]; vector<pii> g[N]; vector<pair<int, ll>> ng[N]; int dep[N]; int f[N][20]; bool st[N]; ll f2[N][20]; int find(int x) {if (p[x] != x)p[x]= find(p[x]);return p[x]; } // void dfs(int u,int fa,int top,ll sum=0){ // for(auto j:v[u]){ // if(j.x==fa) continue; // if(j.x>k) // dfs(j.x,u,top,sum+j.y); // else // { // g[top].push_back({j.x,j.y}); // dfs(j.x,u,j.x,0); // } // } // } void dfs2(int u, int fa, ll faw) {dep[u]= dep[fa] + 1;f[u][0]= fa;f2[u][0]= faw;for (auto j : ng[u]) {if (j.x == fa)continue;dfs2(j.x, u, j.y);} } ll maxlca(int a, int b) {ll maxv= 0;if (dep[a] < dep[b])swap(a, b);for (int i= 19; i >= 0; i--)if (dep[f[a][i]] >= dep[b]) {maxv= max(maxv, f2[a][i]);a= f[a][i];}if (a == b)return maxv;for (int i= 19; i >= 0; i--)if (f[a][i] != f[b][i]) {maxv= max(maxv, f2[a][i]);maxv= max(maxv, f2[b][i]);a= f[a][i], b= f[b][i];}maxv= max(maxv, max(f2[a][0], f2[b][0]));return maxv; } void dijkstra() {priority_queue<pii, vector<pii>, greater<pii>> q;for (int i= 0; i <= n; i++)dist[i]= 1e18;dist[0]= 0;q.push({0, 0});while (q.size()) {auto tt= q.top();q.pop();if (st[tt.y])continue;st[tt.y]= 1;for (auto j : g[tt.y]) {if (dist[j.x] > dist[tt.y] + j.y) {dist[j.x]= dist[tt.y] + j.y;if (!st[j.x])q.push({dist[j.x], j.x});}}} } void init() {for (int i= 1; i <= 19; i++)for (int u= 1; u <= n; u++) {f[u][i]= f[f[u][i - 1]][i - 1], f2[u][i]= max(f2[u][i - 1], f2[f[u][i - 1]][i - 1]);} } int main() {// ios::sync_with_stdio(0);// cin.tie(0);// cout.tie(0);cin >> n >> m >> k >> _;newcnt= k;for (int i= 0; i < m; i++) {int a, b, c;scanf("%d%d%d", &a, &b, &c);q[i]= {a, b, c};}for (int i= 1; i <= n; i++)p[i]= i;int A, B;for (int i= 0; i < m; i++) {int a, b;a= q[i].a;b= q[i].b;g[a].push_back({b, q[i].c});g[b].push_back({a, q[i].c});}for (int i= 1; i <= k; i++)g[0].push_back({i, 0});dijkstra();for (int i= 0; i < m; i++) {q[i].c= dist[q[i].a] + dist[q[i].b] + q[i].c;}sort(q, q + m);int cnt= 0;for (int i= 0; i < m; i++) {ll c= q[i].c;int a= q[i].a;int b= q[i].b;a= find(a);b= find(b);if (a != b) {p[a]= b;// cout << q[i].a << " " << q[i].b << " " << c << endl;ng[q[i].a].push_back({q[i].b, c});ng[q[i].b].push_back({q[i].a, c});cnt++;if (cnt == n - 1)break;}}// dfs(1,0,1,0);dfs2(1, 0, 0);init();while (_--) {int a, b;scanf("%d%d", &a, &b);cout << maxlca(a, b) << endl;}return 0; } /** * In every life we have some trouble * When you worry you make it double * Don't worry,be happy. **/總結
以上是生活随笔為你收集整理的CF1253F Cheap Robot的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 精神恍惚是什么原因?
- 下一篇: 牛客练习赛55E树