bzoj 4289 Tax - 最短路

题目传送门

  这是一条通往vjudge的神秘通道

  这是一条通往bzoj的神秘通道

题目大意

  如果一条路径走过的边依次为$e_{1}, e_{2}, \cdots , e_{k}$,那么它的长度为$e_{1} + \max (e_{1}, e_{2}) + \max (e_{2}, e_{3}) + \cdots + \max (e_{k - 1}, e_{k}) + e_{k}$,问点$1$到点$n$的最短路。

  显然需要把状态记在最后一条边上。

  然后给一个菊花图,这个做法就gg了。

  因此考虑一些黑科技。

  可以把边看成点,然后考虑如何在辺与边之间快速连边。

  对于一个点的出边,可以把它们按照权值排序,大的向比它略小的连一条权值为0的边,小的向比它略大的连一天权值为它们边权之差的边。

  然后原图中每条边向它的反向边连一条边权相同的边。

  然后再建两个虚点,一个起点,向以1为起点的边连边,边权不变。一个终点,以$n$为终点的边向它连边。

Code

  1 /**
  2  * bzoj
  3  * Problem#4289
  4  * Accepted
  5  * Time: 3200ms
  6  * Memory: 31292k
  7  */
  8 #include <bits/stdc++.h>
  9 #ifndef WIN32
 10 #define Auto "%lld"
 11 #else
 12 #define Auto "%I64d"
 13 #endif
 14 using namespace std;
 15 typedef bool boolean;
 16
 17 #define ll long long
 18
 19 typedef class Edge {
 20     public:
 21         int end, next, w;
 22
 23         Edge(int end = 9, int next = 0, int w = 0):end(end), next(next), w(w) {        }
 24 }Edge;
 25
 26 typedef class MapManager {
 27     public:
 28         int ce;
 29         int *h;
 30         Edge *es;
 31
 32         MapManager() {        }
 33         MapManager(int n, int m):ce(-1) {
 34             h = new int[(n + 1)];
 35             es = new Edge[(m + 5)];
 36             memset(h, -1, sizeof(int) * (n + 1));
 37         }
 38
 39         void addEdge(int u, int v, int w) {
 40             es[++ce] = Edge(v, h[u], w);
 41             h[u] = ce;
 42 //            cerr << u << "->" << v << " " << w << endl;
 43         }
 44
 45         Edge& operator [] (int pos) const {
 46             return es[pos];
 47         }
 48 }MapManager;
 49
 50 int n, m;
 51 Edge *es;
 52 vector<int> *dg;
 53 MapManager g;
 54
 55 inline void init() {
 56     scanf("%d%d", &n, &m);
 57     es = new Edge[(m + 1)];
 58     dg = new vector<int>[(n + 1)];
 59     for (int i = 0; i < m; i++) {
 60         scanf("%d%d%d", &es[i].end, &es[i].next, &es[i].w);
 61         dg[es[i].end].push_back(i << 1);
 62         dg[es[i].next].push_back(i << 1 | 1);
 63     }
 64 }
 65
 66 boolean cmp(const int& a, const int& b) {
 67     return es[a >> 1].w < es[b >> 1].w;
 68 }
 69
 70 int s, t;
 71
 72 inline void build() {
 73     g = MapManager((m << 1) + 2, m << 3);
 74     s = m << 1, t = m << 1 | 1;
 75     for (int i = 1; i <= n; i++) {
 76         sort(dg[i].begin(), dg[i].end(), cmp);
 77         for (int j = 1; j < (signed) dg[i].size(); j++) {
 78             int u = (j) ? (dg[i][j - 1]) : (-1), v = dg[i][j];
 79             g.addEdge(v, u, 0);
 80             g.addEdge(u, v, es[v >> 1].w - es[u >> 1].w);
 81         }
 82     }
 83
 84     for (int i = 0; i < (signed) dg[1].size(); i++)
 85         g.addEdge(s, dg[1][i], es[dg[1][i] >> 1].w);
 86     for (int i = 0; i < (signed) dg[n].size(); i++)
 87         g.addEdge(dg[n][i] ^ 1, t, es[dg[n][i] >> 1].w);
 88
 89     for (int i = 0, w; i < m; i++) {
 90         w = es[i].w;
 91         g.addEdge(i << 1, i << 1 | 1, w);
 92         g.addEdge(i << 1 | 1, i << 1, w);
 93     }
 94 }
 95
 96 typedef class Node {
 97     public:
 98         int p;
 99         ll dis;
100
101         Node(int p = 0, ll dis = 0):p(p), dis(dis) {            }
102
103         boolean operator < (Node b) const {
104             return dis > b.dis;
105         }
106 }Node;
107
108 ll *f;
109 priority_queue<Node> que;
110 inline ll dijstra() {
111     f = new ll[(m << 1) + 2];
112     memset(f, 0x3f, sizeof(ll) * ((m << 1) + 2));
113     que.push(Node(s, f[s] = 0));
114     while (!que.empty()) {
115         Node e = que.top();
116         que.pop();
117         if (e.dis != f[e.p])    continue;
118         for (int i = g.h[e.p]; ~i; i = g[i].next) {
119             Node eu (g[i].end, e.dis + g[i].w);
120             if (eu.dis < f[eu.p]) {
121                 f[eu.p] = eu.dis;
122                 que.push(eu);
123             }
124         }
125     }
126     return f[t];
127 }
128
129 inline void solve() {
130     printf(Auto"\n", dijstra());
131 }
132
133 int main() {
134     init();
135     build();
136     solve();
137     return 0;
138 }

原文地址:https://www.cnblogs.com/yyf0309/p/8504265.html

时间: 2024-10-10 04:52:14

bzoj 4289 Tax - 最短路的相关文章

bzoj 4289 TAX —— 点边转化

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4289 把边转化成点,同一个原有点相连的边中,边权小的向大的连差值的边,大的向小的连0的边: 一开始想的是给每个新点记一个点权是这个点(边)原来的权,走到它时先加上点权,因为要在原图上经过这条边还是要花费边权: 但是这样在原图中的边之间转移时会把它们的边权都加上,就不对了: 所以应该是把原图的边进一步拆成两个点,两端点的集合各加入一个,这两点之间连原边权的边: 题目上什么也没说...总之 d

●BZOJ 4289 PA2012 Tax

●赘述题目 算了,题目没有重复的必要. 注意理解:对答案造成贡献的是每个点,就是了. 举个栗子: 对于如下数据: 2 1 1 2 1 答案是 2: ●题解 方法:建图(难点)+最短路. 先来几个链接:(他们为我解题提供了思路,但有些部分看得我有点mengbi) ●http://blog.csdn.net/pure_w/article/details/55060079 ●http://www.cnblogs.com/clrs97/p/5046933.html 建图: 1.把原图的双向边拆成两条单向

BZOJ.4289.PA2012 Tax(思路 Dijkstra)

题目链接 \(Description\) 给出一个N个点M条边的无向图,经过一个点的代价是进入和离开这个点的两条边的边权的较大值,求从起点1到点N的最小代价.起点的代价是离开起点的边的边权,终点的代价是进入终点的边的边权. \(Solution\) 最直接的方法是把每条边作为一个点,对于连接同一个点的两条边连一条新边,最后把连接1和n的点分别连S.T,跑最短路 但这样边数是O(m^2)的 对于路径上相邻两条边\((i,j,v1)\)和\((j,k,v2)\),v1<v2,考虑如何构图把v1比v2

BZOJ 4289: PA2012 Tax

Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 755  Solved: 240[Submit][Status][Discuss] Description 给出一个N个点M条边的无向图,经过一个点的代价是进入和离开这个点的两条边的边权的较大值,求从起点1到点N的最小代价.起点的代价是离开起点的边的边权,终点的代价是进入终点的边的边权 N<=100000 M<=200000 Input Output Sample Input 4 5 1 2 5 1

【BZOJ-4289】Tax 最短路 + 技巧建图

4289: PA2012 Tax Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 168  Solved: 69[Submit][Status][Discuss] Description 给出一个N个点M条边的无向图,经过一个点的代价是进入和离开这个点的两条边的边权的较大值,求从起点1到点N的最小代价.起点的代价是离开起点的边的边权,终点的代价是进入终点的边的边权 N<=100000 M<=200000 Input Output Sample I

bzoj 4398 福慧双修 - 最短路

Description 菩萨为行,福慧双修,智人得果,不忘其本.——唐朠立<大慈恩寺三藏法师传>有才而知进退,福慧双修,这才难得.——乌雅氏如何福慧双修?被太后教导的甄嬛徘徊在御花园当中.突然,她发现御花园中的花朵全都是红色和蓝色的.她冥冥之中得到了响应:这就是指导她如何福慧双修的! 现在御花园可以看作是有N块区域,M条小路,两块区域之间可通过小路连接起来.现在甄嬛站在1号区域,而她需要在御花园中绕一绕,且至少经过1个非1号区 域的区域.但是恰好1号区域离碎玉轩最近,因此她最后还是要回到1号区

【BZOJ 3040】 最短路(road)

3040: 最短路(road) Time Limit: 60 Sec  Memory Limit: 200 MB Submit: 1749  Solved: 523 [Submit][Status] Description N个点,M条边的有向图,求点1到点N的最短路(保证存在). 1<=N<=1000000,1<=M<=10000000 Input 第一行两个整数N.M,表示点数和边数. 第二行六个整数T.rxa.rxc.rya.ryc.rp. 前T条边采用如下方式生成: 1.初

【BZOJ】2125: 最短路 圆方树(静态仙人掌)

[题意]给定带边权仙人掌图,Q次询问两点间最短距离.n,m,Q<=10000 [算法]圆方树处理仙人掌问题 [题解]树上的两点间最短路问题,常用倍增求LCA解决,考虑扩展到仙人掌图. 先对仙人掌图建圆方树,圆圆边和原图边权一致.对于每个方点代表的环,记深度最小的点为x,则圆方边的边权是圆点到x的最短距离. 若lca(u,v)为圆点,则两点间最短路转化为圆方树上dis[u]+dis[v]-2*dis[lca].(向上延伸的路径,经过环则必然经过每个方点的x,计算无误) 若lca(u,v)为方点,则

BZOJ 1003 dp+最短路

1003: [ZJOI2006]物流运输 题意:m个码头,从码头1到码头m,连续n天都要运送货物.每一天的花费是总路线长度大小,但如果和前一天的路线不一样,要另处加上k元花费.而且有些码头有些天不能用,问这n天的最小费用. tags:菜鸡一开始真没想到是dp 求n天时最小花费,就要想到以天数为阶段进行规划.dp[i][j]表示第i天到第j天走同一条路线的花费,则f[i]=min( f[i], f[j]+dp[j+1][i]+k ). #include<bits/stdc++.h> using