4289: PA2012 Tax

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 168  Solved: 69
[Submit][Status][Discuss]

Description

给出一个N个点M条边的无向图,经过一个点的代价是进入和离开这个点的两条边的边权的较大值,求从起点1到点N的最小代价。起点的代价是离开起点的边的边权,终点的代价是进入终点的边的边权
N<=100000
M<=200000

Input

Output

Sample Input

4 5
1 2 5
1 3 2
2 3 1
2 4 4
3 4 8

Sample Output

12

HINT

Source

Solution

比较有技巧的建图

首先考虑暴力点的建图:

把每条无向边拆成两条有向边.把每条边看成一个点,对于两条边a->b,b->c

在这两条边之间连有向边,边权为这两条边的权值的较大值.

新建源点S,汇点T, S向所有从1连出去的边连边,所有指向n的边向T连边. 求S->T的最短路即可.

这样的复杂度会达到$O(m^{2})$

考虑优化一下,有个类似网络流中补流思想的方法:

考虑利用差值来建边.

依然把每条边x-y拆成x->y,y->x.

枚举每个中转点x. 将x的出边按权值排序,x的每条入边向对应的出边连该边权值的边,x的每条出边向第一个比它大的出边连两边权差值的边,x的每条出边向第一个比它小的出边连权值为0的边. 新建源汇S,T S向每条1的出边连权值为该边边权的边.每条n的入边向T连该边权值的边.

跑S->T的最短路即可.

这样的复杂度是$O(mlogm)$就可以AC

顺带提一句,用Dijkstra效率很快

Code

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
using namespace std;
void Freopen() {freopen("travel.in","r",stdin); freopen("travel.out","w",stdout);}
#define Pa pair<long long,int>
inline int read()
{
int x=,f=; char ch=getchar();
while (ch<'' || ch>'') {if (ch=='-') f=-; ch=getchar();}
while (ch>='' && ch<='') {x=x*+ch-''; ch=getchar();}
return x*f;
}
#define MAXN 200010
#define INF 1LL<<60
int N,M;
struct EdgeNode{int next,to,val;}edge[MAXN<<],road[MAXN<<];
int head[MAXN],cnt=,first[MAXN<<],tot=;
inline void AddEdge(int u,int v,int w) {cnt++; edge[cnt].next=head[u]; head[u]=cnt; edge[cnt].to=v; edge[cnt].val=w;}
inline void InsertEdge(int u,int v,int w) {AddEdge(u,v,w); AddEdge(v,u,w);}
inline void AddRoad(int u,int v,int w) {tot++; road[tot].next=first[u]; first[u]=tot; road[tot].to=v; road[tot].val=w;}
inline bool cmp(int x,int y) {return edge[x].val<edge[y].val;}
priority_queue<Pa,vector<Pa>,greater<Pa> >q;
int S,T;
long long dis[MAXN<<];
void Dijkstra()
{
for (int i=S; i<=T; i++) dis[i]=INF;
q.push(make_pair(,S)); dis[S]=;
while (!q.empty())
{
int now=q.top().second;
long long Dis=q.top().first;
q.pop();
if (Dis>dis[now]) continue;
for (int i=first[now]; i; i=road[i].next)
if (dis[now]+road[i].val<dis[road[i].to])
dis[road[i].to]=dis[now]+road[i].val,
q.push(make_pair(dis[road[i].to],road[i].to));
}
}
int st[MAXN<<],tp;
void BuildGraph()
{
S=,T=*(M+);
for (int i=; i<=N; i++)
{
tp=;
for (int j=head[i]; j; j=edge[j].next)
st[++tp]=j;
sort(st+,st+tp+,cmp);
for (int j=; j<=tp; j++)
{
int now=st[j],suc=st[j+];
if (edge[now].to==N) AddRoad(now,T,edge[now].val);
if (i==) AddRoad(S,now,edge[now].val);
AddRoad(now^,now,edge[now].val);
if (j<tp) AddRoad(now,suc,edge[suc].val-edge[now].val),AddRoad(suc,now,);
}
}
}
int main()
{
// Freopen();
N=read(),M=read();
for (int x,y,z,i=; i<=M; i++) x=read(),y=read(),z=read(),InsertEdge(x,y,z);
BuildGraph();
Dijkstra();
printf("%lld\n",dis[T]);
return ;
}

小压一波常数,成功跑到rank2..想怒压300ms到rank1时,失误反而慢了300ms....23333

Orz现场裸跑最短路80分的梁哥....

貌似还有一种类似于DP的方法?

【BZOJ-4289】Tax 最短路 + 技巧建图的更多相关文章

  1. 【BZOJ-4289】Tax 最短路 + 技巧建图(化边为点)

    题意 给出一个N个点M条边的无向图,经过一个点的代价是进入和离开这个点的两条边的边权的较大值,求从起点1到点N的最小代价.起点的代价是离开起点的边的边权,终点的代价是进入终点的边的边权N<=10 ...

  2. [Bzoj4289]PA2012 Tax(Dijkstra+技巧建图)

    Description 给出一个N个点M条边的无向图,经过一个点的代价是进入和离开这个点的两条边的边权的较大值,求从起点1到点N的最小代价.起点的代价是离开起点的边的边权,终点的代价是进入终点的边的边 ...

  3. bzoj 4289 Tax - 最短路

    题目传送门 这是一条通往vjudge的神秘通道 这是一条通往bzoj的神秘通道 题目大意 如果一条路径走过的边依次为$e_{1}, e_{2}, \cdots , e_{k}$,那么它的长度为$e_{ ...

  4. [BZOJ4289] [PA2012] Tax 解题报告 (最短路+差分建图)

    题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=4289 4289: PA2012 Tax Time Limit: 10 Sec  Memo ...

  5. LOJ#6354. 「CodePlus 2018 4 月赛」最短路[最短路优化建图]

    题意 一个 \(n\) 个点的完全图,两点之间的边权为 \((i\ xor\ j)*C\) ,同时有 \(m\) 条额外单向路径,问从 \(S\) 到 \(T\) 的最短路. \(n\leq 10^5 ...

  6. bzoj 2259 [Oibh]新型计算机 ——最短路(建图)

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2259 不是 n^2 条边!连那条边权为0的边之后,只要每个位置向它的前一个位置和后一个位置连 ...

  7. 牛客网NOIP赛前集训营-提高组(第八场)-B-推箱子[最短路优化建图]

    题意 有 \(n\) 个箱子,指定一个箱子开始向右推,如果碰到了别的箱子会令其移动,问 \(k\) 秒之后每个箱子所在的位置. \(n\leq 10^5\). 分析 转化成最短路模型,如果两个箱子 \ ...

  8. uva 1048 最短路的建图 (巧,精品)

    大白书 P341这题说的是给了NT种飞机票,给了价钱和整个途径,给了nI条要旅游的路线.使用飞机票都必须从头第一站开始坐,可以再这个路径上的任何一点下飞机一但下飞机了就不能再上飞机,只能重新买票,对于 ...

  9. bzoj 4289 TAX —— 点边转化

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4289 把边转化成点,同一个原有点相连的边中,边权小的向大的连差值的边,大的向小的连0的边: ...

随机推荐

  1. Linux的chattr与lsattr命令

    有时候你发现用root权限都不能修改某个文件,大部分原因是曾经用chattr命令锁定该文件了.chattr命令的作用很大,其中一些功能是由Linux内核版本来支持的,不过现在生产绝大部分跑的linux ...

  2. 夯实基础之php学习-2提高篇

    1,Jpgraph, 详见Php图形化jpgraph 2,文件系统 文件的操作步骤:打开文件->操作文件->关闭文件 打开文件fopen(filename,mode) 关闭文件fclose ...

  3. 简易安装python统计包

    PythonCharm简易安装python统计包及 本文介绍使用pythonCharm IDE 来安装Python统计包或一些packages的简单过程,基本无任何技术难度,顺便提一提笔者在安装过程中 ...

  4. swift导航栏导航按钮添加多个按钮事件

    //导航左边返回按钮 let button1 = UIButton(frame:CGRectMake(0, 0, 18, 18)) button1.setImage(Constant.Image.Na ...

  5. unity3d CarWaypoints插件

    编写初衷: 1.网上没有现成的好用的waypoints插件 2.自己在做一个赛车游戏,如果没有这款插件的话在制作游戏的过程中会被累成狗 3.从来没有接触过插件方面的东西,所以想自己尝试一下 插件用途: ...

  6. 几张图弄明白ios布局中的尺寸问题

    背景 先说说逆向那事.各种曲折..各种技术过时,老老实实在啃看雪的帖子..更新会有的. 回正题,这里讨论的是在Masnory框架下的布局问题.像我这种游击队没师傅带,什么都得自己琢磨,一直没闹明白下面 ...

  7. X240s安装Win7 以及如何启用ExpressCache

    新买了一台X240S笔记本,尝试了带的Win8正版一个月后,实在无法适应Win8,干脆退回Win7完事,以下为安装过程, 第一步:制作启动U盘 首先,下载一个iso格式的Win7安装镜像文件,利用微软 ...

  8. jaccard similarity coefficient 相似度计算

    Jaccard index From Wikipedia, the free encyclopedia     The Jaccard index, also known as the Jaccard ...

  9. oracle 10g编程

    一.概述 1.sql语言特点 sql语言采用集合操作方式,对数据的处理是成组进行的,而不是一条一条处理,听过使用集合操作方式,可以家加快数据的处理速度. 执行sql语句时每次只能发送并处理一条语句.如 ...

  10. 通过Gearman实现MySQL到Redis的数据同步

    对于变化频率非常快的数据来说,如果还选择传统的静态缓存方式(Memocached.File System等)展示数据,可能在缓存的存取上会有很大的开销,并不能很好的满足需要,而Redis这样基于内存的 ...