【BZOJ-4289】Tax 最短路 + 技巧建图(化边为点)
题意
给出一个N个点M条边的无向图,经过一个点的代价是进入和离开这个点的两条边的边权的较大
值,求从起点1到点N的最小代价。起点的代价是离开起点的边的边权,终点的代价是进入终
点的边的边权
N<=100000
M<=200000
题解一
- 无向图连边时要拆成两条边,这大家都知道
- 然后把边看成”点”,(优化:)因为不可能每个”点”之间都能连边,所以
- 对除了 1点和 n点之外的点连出去的边(真实边)按权值从小到大排个序,边看作”点”
- 然后 i “点”向 i + 1”点”连一条边值为(化点之前的两条边的权值差);i “点”向 i - 1”点”连一条权值为0LL的边;然后每个”点”和它反向边化成的”点”连一条边值为该边以前权值的边。
- 然后用堆优化的dij跑一遍最短路,求出dis[i]( dis[i] = 初始点 到 i “点”的最短距离)。
- 最短路初始过程:将原点1连出去的 边看成点 后,加入队列。
- 求值:枚举连向终点n的边,维护ans = minj{dis[i^1] + val[i]}// i 是边的编号
题解二
比较有技巧的建图
首先考虑暴力点的建图:
把每条无向边拆成两条有向边.把每条边看成一个点,对于两条边a->b,b->c
在这两条边之间连有向边,边权为这两条边的权值的较大值.
新建源点S,汇点T, S向所有从1连出去的边连边,所有指向n的边向T连边. 求S->T的最短路即可.
这样的复杂度会达到O(m2)O(m2)
考虑优化一下,有个类似网络流中补流思想的方法:
考虑利用差值来建边.
依然把每条边x-y拆成x->y,y->x.
枚举每个中转点x. 将x的出边按权值排序,x的每条入边向对应的出边连该边权值的边,x的每条出边向第一个比它大的出边连两边权差值的边,x的每条出边向第一个比它小的出边连权值为0的边. 新建源汇S,T S向每条1的出边连权值为该边边权的边.每条n的入边向T连该边权值的边.
跑S->T的最短路即可.
这样的复杂度是O(mlogm)O(mlogm)就可以AC
顺带提一句,用Dijkstra效率很快
C++代码
#include <bits/stdc++.h>
using namespace std; const int maxn = 1e5 + ; struct Edge{
int from,to;
int w,nxt;
}edge[maxn << ],e[maxn << ]; int n , m ;
int pre[maxn];
int fa[maxn],cost[maxn],dep[maxn];
int head[maxn],tot; void init(){
tot = ;
memset(head,-,sizeof head);
for(int i = ;i <= n ; i++){
pre[i] = i;
}
} bool cmp(Edge a,Edge b){
return a.w < b.w;
} void add_edge(int u ,int v,int w){
e[tot].from = u;
e[tot].to = v;
e[tot].w = w;
e[tot].nxt = head[u];
head[u] = tot ++;
} inline int find(int x){if(x == pre[x])return x;else return pre[x] = find(pre[x]);} void kruskal(){
sort(edge+,edge++m,cmp);
int fu,fv,u,v;
for(int i = ;i <= m; i++){
u = edge[i].from;
v = edge[i].to;
fu = find(u);
fv = find(v);
if(fu != fv){
pre[fu] = fv;
add_edge(u,v,edge[i].w);
add_edge(v,u,edge[i].w);
}
}
} void dfs(int u,int Fa,int step){
int v;
for(int i = head[u]; ~i ;i = e[i].nxt){
v = e[i].to;
if(v ==Fa) continue;
dep[v] = step;
fa[v] = u;
cost[v] = e[i].w;
dfs(v,u,step + );
}
} int lca(int u,int v){
int du = dep[u];
int dv = dep[v];
int res = ;
while(du > dv){
res = max(res,cost[u]);
u = fa[u];
du --;
}
while(dv > du){
res = max(res,cost[v]);
v = fa[v];
dv --;
}
while(u != v){
res = max(res,cost[u]);
res = max(res,cost[v]);
u = fa[u];
v = fa[v];
}
return res;
} int main(){
int cas = ;
while(cin >> n >> m){
if(cas) puts("");
else cas ++;
init();
for(int i = ;i <= m; i ++){
int u , v , w;
cin >> u >> v >> w;
edge[i].from = u;
edge[i].to = v;
edge[i].w = w;
}
//cout << 1 ;
kruskal();
fa[] = cost[] = dep[] = ;
dfs(,-,);
int q;
cin >> q;
while(q--){
int u , v ;
cin >> u >> v;
cout << lca(u,v) << endl;
}
}
return ;
}
【BZOJ-4289】Tax 最短路 + 技巧建图(化边为点)的更多相关文章
- 【BZOJ-4289】Tax 最短路 + 技巧建图
4289: PA2012 Tax Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 168 Solved: 69[Submit][Status][Dis ...
- [Bzoj4289]PA2012 Tax(Dijkstra+技巧建图)
Description 给出一个N个点M条边的无向图,经过一个点的代价是进入和离开这个点的两条边的边权的较大值,求从起点1到点N的最小代价.起点的代价是离开起点的边的边权,终点的代价是进入终点的边的边 ...
- bzoj 4289 Tax - 最短路
题目传送门 这是一条通往vjudge的神秘通道 这是一条通往bzoj的神秘通道 题目大意 如果一条路径走过的边依次为$e_{1}, e_{2}, \cdots , e_{k}$,那么它的长度为$e_{ ...
- [BZOJ4289] [PA2012] Tax 解题报告 (最短路+差分建图)
题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=4289 4289: PA2012 Tax Time Limit: 10 Sec Memo ...
- LOJ#6354. 「CodePlus 2018 4 月赛」最短路[最短路优化建图]
题意 一个 \(n\) 个点的完全图,两点之间的边权为 \((i\ xor\ j)*C\) ,同时有 \(m\) 条额外单向路径,问从 \(S\) 到 \(T\) 的最短路. \(n\leq 10^5 ...
- bzoj 2259 [Oibh]新型计算机 ——最短路(建图)
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2259 不是 n^2 条边!连那条边权为0的边之后,只要每个位置向它的前一个位置和后一个位置连 ...
- 牛客网NOIP赛前集训营-提高组(第八场)-B-推箱子[最短路优化建图]
题意 有 \(n\) 个箱子,指定一个箱子开始向右推,如果碰到了别的箱子会令其移动,问 \(k\) 秒之后每个箱子所在的位置. \(n\leq 10^5\). 分析 转化成最短路模型,如果两个箱子 \ ...
- uva 1048 最短路的建图 (巧,精品)
大白书 P341这题说的是给了NT种飞机票,给了价钱和整个途径,给了nI条要旅游的路线.使用飞机票都必须从头第一站开始坐,可以再这个路径上的任何一点下飞机一但下飞机了就不能再上飞机,只能重新买票,对于 ...
- bzoj 4289 TAX —— 点边转化
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4289 把边转化成点,同一个原有点相连的边中,边权小的向大的连差值的边,大的向小的连0的边: ...
随机推荐
- 1003: [ZJOI2006]物流运输
就我一开始写状压的吗? 调不过 后来发现(直接搜索)直接最短路就行了-- \(f[i]\)表示前\(i\)天最少需要多少 \(f[i] = min(f[j] + dis(j + 1, i))\) 然后 ...
- 经典DP模型--回文词--IOI2000
[问题描述]回文词是一种对称的字符串--也就是说, 一个回文词, 从左到右读和从右到左读得到的结果是一样的. 任意给定一个字符串, 通过插入若干字符, 都可以变成一个回文词. 你的任务是写一个程序, ...
- C_clock()测试代码(循环)运行时间
clock() 传送门(百度百科) clock()是C/C++中的计时函数,而与其相关的数据类型是clock_t.在MSDN中,查得对clock函数定义如下: clock_t clock(voi ...
- JS框架_(JQbar.js)柱状图动态百分比进度条特效
百度云盘 传送门 密码:q6rt 柱状图动态百分比进度条效果 <html> <head> <title>jqbar.js柱状图动态百分比进度条特效</titl ...
- nginx负载均衡 理解与测试
Nginx负载均衡概述 Web服务器,直接面向用户,往往要承载大量并发请求,单台服务器难以负荷,我使用多台WEB服务器组成集群,前端使用Nginx负载均衡,将请求分散的打到我们的后端服务器集群中,实现 ...
- @RepositoryRestResource注解的使用
1.Build with Maven <?xml version="1.0" encoding="UTF-8"?> <project xmln ...
- Android-Universal-Image-Loader的缓存处理机制与使用 LruCache 缓存图片
讲到缓存,平时流水线上的码农一定觉得这是一个高大上的东西.看过网上各种讲缓存原理的文章,总感觉那些文章讲的就是玩具,能用吗?这次我将带你一起看过UIL这个国内外大牛都追捧的图片缓存类库的缓存处理机制. ...
- android中如何自动获取短信验证码
package com.loaderman.smsbroadcastreceiver; import java.util.regex.Matcher; import java.util.regex.P ...
- pureftp安装部署
ftp:文件传输pure-ftpd:ftp软件作用:通过映射登录传送和接收文件.1.先下载pure-ftpd软件,最好指定一个下载软件目录如:/usr/local/src wget https://d ...
- 阶段3 2.Spring_07.银行转账案例_6 测试转账并分析案例中的问题
转账回滚这里把异常打印出来.AccountServiceTest.java 把数据库的金额现在都改成1000块 运行测试方法 这里已经报错了. 刷新数据库内的数据.这样我们事物就控制成功了. 事物控制 ...