【图论】【斜率优化】前往大都会(loj 2769)
生活随笔
收集整理的這篇文章主要介紹了
【图论】【斜率优化】前往大都会(loj 2769)
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
正題
jzoj 7181
題目大意
給你由若干鐵路組成的圖(一個(gè)鐵路上有若干點(diǎn)),問你從1到n在最短路徑的前提下,乘坐的每一條鐵路所花費(fèi)時(shí)間的平方和的最大值
解題思路
先用dij跑出最短路圖(即長度等于最短路的所有路徑)
然后在最短路圖上DP,設(shè)fif_ifi?為到第i個(gè)點(diǎn)滿足最短路的最大答案,轉(zhuǎn)移方程
fi=max(fj+(disi?disj)2)f_i = max\ (f_j+(dis_i-dis_j)^2)fi?=max?(fj?+(disi??disj?)2)
對(duì)于該方程,可以用斜率優(yōu)化
當(dāng)計(jì)算到i時(shí),枚舉所在鐵路,然后斜率優(yōu)化(因?yàn)槿ax,且dis單調(diào)遞增,所以用單調(diào)棧維護(hù)上凸殼)
代碼
#include<queue> #include<vector> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define ll long long #define mp make_pair #define fs first #define sn second #define sz st[g].size() #define l1 st[g][sz - 1] #define l2 st[g][sz - 2] #define N 1000100 using namespace std; int n, m, x, y, nn, tot, cnt, p[N], q[N], h[N]; ll z, f[N], X[N], Y[N], dis[N]; vector<pair<int, int> >w[N]; vector<pair<int, ll> >a[N]; vector<int>st[N<<1], wst[N]; priority_queue<pair<ll, int> >d; struct rec {int to, next;ll l; }e[N]; void add(int x, int y, ll z) {e[++tot].to = y;e[tot].l = z;e[tot].next = h[x];h[x] = tot; } void dij() {memset(dis, 0x7f, sizeof(dis));dis[1] = 0;d.push(mp(0, 1));while(!d.empty()){int u = d.top().sn;d.pop();if (p[u]) continue;p[u] = 1;for (int i = h[u]; i; i = e[i].next){int v = e[i].to;if (dis[u] + e[i].l < dis[v]){dis[v] = dis[u] + e[i].l;d.push(mp(-dis[v], v));}}}return; } bool cmp(int x, int y) {return dis[x] < dis[y]; } void solve() {for (int i = 1; i <= n; ++i)q[i] = i;//按dis枚舉sort(q + 1, q + 1 + n, cmp);for (int i = 1; i <= n; ++i){int u = q[i];for (int j = 0; j < w[u].size(); ++j){x = w[u][j].fs;y = w[u][j].sn;if (y && dis[a[x][y - 1].fs] + a[x][y - 1].sn == dis[u]) wst[x][y] = wst[x][y - 1];//一個(gè)鐵路可能在不同的最短路中,先判斷在哪一段中else wst[x][y] = ++cnt;int g = wst[x][y];while(sz >= 2 && Y[l1] - Y[l2] < 2ll * dis[u] * (X[l1] - X[l2]))//斜率優(yōu)化st[g].pop_back();if (sz){int v = st[g][sz - 1];f[u] = max(f[u], f[v] + (dis[u] - dis[v]) * (dis[u] - dis[v]));}}Y[u] = f[u] + dis[u] * dis[u];X[u] = dis[u];for (int j = 0; j < w[u].size(); ++j){x = w[u][j].fs;y = w[u][j].sn;int g = wst[x][y];while (sz >= 2 && (Y[l1] - Y[l2]) * (X[u] - X[l1]) < (Y[u] - Y[l1]) * (X[l1] - X[l2]))st[g].pop_back();st[g].push_back(u);}} } int main() {scanf("%d%d", &n, &m);for (int i = 1; i <= m; ++i){scanf("%d", &nn);scanf("%d", &x);for (int j = 1; j <= nn; ++j){scanf("%lld%d", &z, &y);add(x, y, z);w[x].push_back(mp(i,j - 1));//在哪一段鐵路的那個(gè)點(diǎn)a[i].push_back(mp(x,z));//插入到第i段鐵路中,到下一個(gè)點(diǎn)的距離為zwst[i].push_back(0);x = y;}w[x].push_back(mp(i,nn));a[i].push_back(mp(x,0));wst[i].push_back(0);}dij();solve();printf("%lld %lld", dis[n], f[n]);return 0; }總結(jié)
以上是生活随笔為你收集整理的【图论】【斜率优化】前往大都会(loj 2769)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 日本小哥发明玩手机防砸脸神器,就是挺费手
- 下一篇: 如何给自己的台式机增加一个硬盘电脑如何加