「BZOJ 4289」 PA2012 Tax
「BZOJ 4289」 PA2012 Tax
题目描述
给出一个 \(N\) 个点 \(M\) 条边的无向图,经过一个点的代价是进入和离开这个点的两条边的边权的较大值,求从起点 \(1\) 到点 \(N\) 的最小代价。起点的代价是离开起点的边的边权,终点的代价是进入终点的边的边权
\(N \leq 10^5, M \leq 2 \times 10^5\)
### 解题思路 :
首先考虑一个暴力的做法,建一个新图,把每一条边看成新图的一个点‘
对于原图的每一个点 \(u\) 对于边 \((u, x), (u, y)\) 在新图中连边 \((u, x) \rightarrow (u, y) = \max(val_{(u, x)}, val_{(u, y)})\)
这样做的复杂度是 \(O(\sum deg_u^2 logn)\),一个菊花图就 \(TLE\) 了
考虑简化新图的边数,不妨观察新图的是怎么得到的
对于原图的一个点,所有与其相邻的连的边在新图都两两连边,其表示从一条边进这个点,从一条边出这个点,边权是两条边的 \(\max\)
观察发现,虽然原图一个点在新图中能产生的边多达 \(deg^2\) 条,但是边的权值只有最多 \(deg\) 种
不妨对原图一个点周围的边按照权值从小到大排序,相邻两条边连一条 \(i \rightarrow i+1\) 的有向边,权值为 \(val_{i+1} - val_i\)
那么从一条较小的边进去,从一条较大的边出来的话,一路经过的权值和恰好等于较大的边的权值
但是可能是从较大的边进入一个点,同时判断走这条边是否真的离开了这个点也很困难,于是就需要分类讨论了
观察发现,可以把一个点周围的边按照权值排序后看成一个环,答案的形态就是从一个环经过一些环内的边再通过一条环边到达另外一个环,以此反复
那么不妨把新图的一个点拆成两个点,\(u\) 表示这个点此时属于原图编号较小的点对应的环, \(u'\) 表示属于原图编号较大的点对应的环
考虑每当从一个环进到另外一个环时,设一个初始权值 $x $ 等于入环的边的边权,如果 \(x\) 是较小的边,那么沿着边权为 \(val_{i+1} - val_i\) 的有向边出环,否则就走边权为 \(0\) 的有向边出环,这样保证了出环时的权值正确
所以只需要对于每个点的相连边按照权值排序后,从小到大相邻的点连 \(val_i+1 - val_i\) 的有向边,从大到小连边为 \(0\) 的有向边,然后在出环的时候 \(u\) 和 \(u'\) 连一条权值为 \(val_u\) 的无向边即可,这样点数是 \(O(2m)\),边数是 \(O(3m)\)
注意要保证同一个环内连的边其对应的端点是同一个,而不是全都是 \(u\) 或 \(u'\) ,剩余的只需要跑一遍 \(Dijkstra\) 即可
复杂度是\(O(mlogm)\)
/*program by mangoyang*/
#include<bits/stdc++.h>
#define inf ((ll) (1e18))
#define Max(a, b) ((a) > (b) ? (a) : (b))
#define Min(a, b) ((a) < (b) ? (a) : (b))
typedef long long ll;
using namespace std;
template <class T>
inline void read(T &x){
int f = 0, ch = 0; x = 0;
for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = 1;
for(; isdigit(ch); ch = getchar()) x = x * 10 + ch - 48;
if(f) x = -x;
}
#define int ll
const int N = 2000005;
int a[N], b[N], nxt[N], head[N], cnt;
int dis[N], n, m;
struct Edge{
int id, x, y, val;
inline int bel(int u){ return (int)(min(x, y) == u); }
}; vector<Edge> g[N];
inline bool cmp(Edge A, Edge B){ return A.val < B.val; }
inline void add(int x, int y, int z){
a[++cnt] = y, b[cnt] = z, nxt[cnt] = head[x], head[x] = cnt;
}
inline void Addedge(int u){
// x + m表示边 x 挂在编号较小的点围成的环上所产生的节点
// x 表示边 x 挂在编号较大的点围城的环上所产生的节点
// 同编号环(x -> y) 小到大 val = y.val - x.val
// 同编号环(x -> y) 大到小 val = 0
// 异编号环(x -> y) 小到大/大到小 val = y.val
sort(g[u].begin(), g[u].end(), cmp);
for(int i = 0, x, y; i < g[u].size(); i++){
if(i){
x = g[u][i].id + g[u][i].bel(u) * m;
y = g[u][i-1].id + g[u][i-1].bel(u) * m;
add(x, y, 0);
}
if(i < g[u].size() - 1){
x = g[u][i].id + g[u][i].bel(u) * m;
y = g[u][i+1].id + g[u][i+1].bel(u) * m;
add(x, y, g[u][i+1].val - g[u][i].val);
}
x = g[u][i].id + g[u][i].bel(u) * m;
y = g[u][i].id + (g[u][i].bel(u) ^ 1) * m;
add(x, y, g[u][i].val);
}
}
struct Node{
int d, id;
bool operator < (const Node &A) const{ return d > A.d; }
}; priority_queue<Node> pq;
inline void Dijkstra(int S){
for(int i = 0; i <= 2 * m + 1; i++) dis[i] = inf / 3;
pq.push((Node){0, S}), dis[S] = 0;
while(!pq.empty()){
Node now = pq.top(); pq.pop();
int u = now.id;
if(dis[u] != now.d) continue;
if(u == 2 * m + 1) return;
for(int p = head[u]; p; p = nxt[p]){
int v = a[p];
if(dis[v] > dis[u] + b[p])
dis[v] = dis[u] + b[p], pq.push((Node){dis[v], v});
}
}
}
signed main(){
read(n), read(m);
for(int i = 1, x, y, z; i <= m; i++){
read(x), read(y), read(z);
g[x].push_back((Edge){i, x, y, z});
g[y].push_back((Edge){i, y, x, z});
}
for(int i = 1; i <= n; i++) Addedge(i);
for(int i = 0; i < g[1].size(); i++) add(0, g[1][i].id + m, g[1][i].val);
for(int i = 0; i < g[n].size(); i++) add(g[n][i].id, 2 * m + 1, 0);
Dijkstra(0), cout << dis[2*m+1];
return 0;
}
「BZOJ 4289」 PA2012 Tax的更多相关文章
- 「BZOJ 4228」Tibbar的后花园
「BZOJ 4228」Tibbar的后花园 Please contact lydsy2012@163.com! 警告 解题思路 可以证明最终的图中所有点的度数都 \(< 3\) ,且不存在环长是 ...
- 「BZOJ 3645」小朋友与二叉树
「BZOJ 3645」小朋友与二叉树 解题思路 令 \(G(x)\) 为关于可选大小集合的生成函数,即 \[ G(x)=\sum[i\in c ] x^i \] 令 \(F(x)\) 第 \(n\) ...
- 「BZOJ 4502」串
「BZOJ 4502」串 题目描述 兔子们在玩字符串的游戏.首先,它们拿出了一个字符串集合 \(S\),然后它们定义一个字符串为"好"的,当且仅当它可以被分成非空的两段,其中每一段 ...
- 「BZOJ 2534」 L - gap字符串
「BZOJ 2534」 L - gap字符串 题目描述 有一种形如 \(uv u\) 形式的字符串,其中 \(u\) 是非空字符串,且 \(v\) 的长度正好为 \(L\), 那么称这个字符串为 \( ...
- 「BZOJ 2956」模积和
「BZOJ 2956」模积和 令 \(l=\min(n,m)\).这个 \(i\neq j\) 非常不优雅,所以我们考虑分开计算,即: \[\begin{aligned} &\sum_{i=1 ...
- Solution -「BZOJ 3812」主旋律
\(\mathcal{Description}\) Link. 给定含 \(n\) 个点 \(m\) 条边的简单有向图 \(G=(V,E)\),求 \(H=(V,E'\subseteq E)\ ...
- 「BZOJ 1001」狼抓兔子
题目链接 luogu bzoj \(Solution\) 这个貌似没有什么好讲的吧,直接按照这个给的图建图就好了啊,没有什么脑子,但是几点要注意的: 建双向边啊. 要这么写,中间还要写一个\(whil ...
- 「BZOJ 5188」「Usaco2018 Jan」MooTube
题目链接 luogu bzoj \(Describe\) 有一个\(n\)个节点的树,边有权值,定义两个节点之间的距离为两点之间的路径上的最小边权 给你\(Q\)个询问,问你与点\(v\)的距离大于等 ...
- 「BZOJ 1791」「IOI 2008」Island「基环树」
题意 求基环树森林所有基环树的直径之和 题解 考虑的一个基环树的直径,只会有两种情况,第一种是某个环上结点子树的直径,第二种是从两个环上结点子树内的最深路径,加上环上这两个结点之间的较长路径. 那就找 ...
随机推荐
- JQuery对RadioButton和CheckButton的操作
js对RadioButton和CheckButton的操作,在网站开发中会经常遇到,而JQuery操作RadioButton和CheckButton非常便捷.小编觉得网站开发人员有必要熟练掌握.所以小 ...
- Metasploit 进阶
本文是"T00LS Metasploit(第二季)"的文档版,是个人在观看视频动手操作的一个记录,仅供学习.文中会介绍Metasploit的一些基本使用:主要包括远程代码执行.MI ...
- 机器学习-kNN(1)
一 kNN算法简介 kNN(K-Nearest Neighbor)工作原理:存在一个样本数据集合,也称为训练样本集,并且样本集中每个数据都存在标签,即我们知道样本集中每一数据与所属分类对应的关系.输入 ...
- koa源码阅读[1]-koa与koa-compose
接上次挖的坑,对koa2.x相关的源码进行分析 第一篇.不得不说,koa是一个很轻量.很优雅的http框架,尤其是在2.x以后移除了co的引入,使其代码变得更为清晰. express和koa同为一批人 ...
- 在wamp下增加多版本的PHP(PHP5.3,PHP5.4,PHP5.5)支持
1.安装WAMPServer 根据自己的操作系统选择相应的WAMP版本,我这里选择WAMPSERVER-32 BITS & PHP 5.5-2.5, 双击安装,选择安装目录即可,超级简单.根据 ...
- OGG相关操作
参数文件详解: 1)truncate ogg 进程: Manager进程:manager进程是配置在源端和目标端 Extract(抽取)进程:部署在源端,用于捕获数据表或者日志中的数据文件: Pump ...
- imperva系统升级遇见的错误(配置文件的导入导出)
今天心态有点炸了 今天去东兴证券做waf升级.浪费了两天才弄完.把客户都弄得有点急了.好歹原厂的工程师耐心的讲解这才弄完.感谢路哥.... 赶紧总结一下. 事情是这样的.东兴 证券的imperva是v ...
- weblogic12.1.3 静默安装 建域
--安装依赖包 yum -y install compat-libcap1 compat-libstdc++ gcc gcc-c++ glibc-devel libaio-devel libstdc+ ...
- 修改系统时间为UTC时间
1 拷贝时区文件 cp /usr/share/zoneinfo/Etc/GMT /etc/localtime 2 修改/etc/profile 在最后添加 TZ="Etc/GMT" ...
- HDU 4300 Clairewd’s message(KMP+思维)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4300 题目大意:题目大意就是给以一段字符xxxxzzz前面x部分是密文z部分是明文,但是我们不知道是从 ...