题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=4289

4289: PA2012 Tax

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 1029  Solved: 310
[Submit][Status][Discuss]

Description

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

Sample Input

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

Sample Output

12

                             [Submit][Status][Discuss]
 

比较有技巧的建图

首先考虑暴力点的建图:

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

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

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

这样的复杂度会达到O(m2)

考虑优化一下:

考虑利用差值来建边.

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

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

仔细看图,L2>L1,发现从S到T的路径走的一定是L2,而不是L1;注意结合上述的建图过程(红色边)

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

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

我的SPFA被T了,估计没写错只是被卡了

以上内容部分参考DaD3zZ大佬的博客

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
#define ll long long
using namespace std; const int N=+;
int n,m,tot1,tot2,S,T;
int head[N],h[N<<],st[N<<],vis[N<<];
ll dist[N<<];
struct EDGE
{
int to;int next;int l;
}edge[N<<],e[N<<];
inline int read()
{
char ch=getchar();
int s=,f=;
while (!(ch>=''&&ch<='')) {if (ch=='-') f=-;ch=getchar();}
while (ch>=''&&ch<='') {s=(s<<)+(s<<)+ch-'';ch=getchar();}
return s*f;
}
void init()
{
memset(head,-,sizeof(head));
memset(h,-,sizeof(h));
memset(dist,0x3f3f3f3f,sizeof(dist));
}
void addedge(int x,int y,int l)
{
edge[tot1]=(EDGE){y,head[x],l};
head[x]=tot1++;
}
bool cmp(int x,int y) {return edge[x].l<edge[y].l;}
void addroad(int x,int y,int l)
{
e[tot2]=(EDGE){y,h[x],l};
h[x]=tot2++;
}
void build()
{
S=*(m+)+;T=*(m+)+;
for (int i=;i<=n;i++)
{
int 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].l);
if (i==) addroad(S,now,edge[now].l);
addroad(now^,now,edge[now].l);
if (j<tp) {addroad(now,suc,edge[suc].l-edge[now].l);addroad(suc,now,);}
}
}
}
priority_queue<pair<ll,int>,vector<pair<ll,int> >,greater<pair<ll,int> > > q;
void Dijkstra()
{
q.push(make_pair(,S));
dist[S]=;
while (!q.empty())
{
int now=q.top().second;
ll Dis=q.top().first;q.pop();
if (Dis>dist[now]) continue;
for (int i=h[now];i!=-;i=e[i].next)
if (dist[now]+e[i].l<dist[e[i].to])
{
dist[e[i].to]=dist[now]+e[i].l;
q.push(make_pair(dist[e[i].to],e[i].to));
}
}
}
int main()
{
n=read();m=read();
init();
for (int i=;i<=m;i++)
{
int x=read(),y=read(),l=read();
addedge(x,y,l);addedge(y,x,l);
}
build();
Dijkstra();
printf("%lld\n",dist[T]);
return ;
}

[BZOJ4289] [PA2012] Tax 解题报告 (最短路+差分建图)的更多相关文章

  1. BZOJ 4289: PA2012 Tax 差分建图 最短路

    https://www.lydsy.com/JudgeOnline/problem.php?id=4289 https://www.cnblogs.com/clrs97/p/5046933.html  ...

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

    4289: PA2012 Tax Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 168  Solved: 69[Submit][Status][Dis ...

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

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

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

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

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

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

  6. [BZOJ4289][PA2012]TAX(最短路)

    首先考虑一种暴力做法,为每条边拆成两条有向边,各建一个点.若某两条边有公共点,则在边所对应的点之间连一条边,权值为两条边中的较大值.这样跑最短路是$O(m^2\log m)$的. 用类似网络流中补流的 ...

  7. BZOJ4289 : PA2012 Tax

    一个直观的想法是把每条边拆成两条有向边,同时每条有向边是新图中的一个点.对于两条边a->b与b->c,两点之间连有向边,费用为两条边费用的最大值.然后新建源点S与汇点T,由S向所有起点为1 ...

  8. bzoj4289 PA2012 Tax——点边转化

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4289 好巧妙的转化!感觉自己难以想出来... 参考了博客:https://blog.csdn ...

  9. 灯光照射,圆形探测类问题(解题报告)<分层差分><cmath取整>

    题目描述 一个n*n的网格图上有m个探测器,每个探测器有个探测半径r,问这n*n个点中有多少个点能被探测到. 输入输出格式 输入格式: (1<=r<n<=5000) (1<=m ...

随机推荐

  1. HDU 4828

    其实..这题是<组合数学>的习题中的一道......当初不会..... 想到一个证明: 填入2n个数,把填在上方的数的位置填上+1,下方的填上-1.这样,在序列1....2n的位置,任意前 ...

  2. CSS3弹性布局内容对齐(justify-content)属性使用具体解释

    内容对齐(justify-content)属性应用在弹性容器上.把弹性项沿着弹性容器的主轴线(main axis)对齐. 该操作发生在弹性长度以及自己主动边距被确定后. 它用来在存在剩余空间时怎样加以 ...

  3. start_kernel——boot_cpu_init及PER_CPU

    init/main.c /* * Activate the first processor. */ static void __init boot_cpu_init(void) { int cpu = ...

  4. Java虚拟机的类载入机制

    Java虚拟机类载入过程是把Class类文件载入到内存.并对Class文件里的数据进行校验.转换解析和初始化,终于形成能够被虚拟机直接使用的java类型的过程. 在载入阶段,java虚拟机须要完毕下面 ...

  5. 关于webuploader跨域解决方法

    1.在iis处理程序映射 2.后台ashx处理添加如下代码

  6. RBAC介绍

    基于角色的权限访问控制(Role-Based Access Control)作为传统访问控制(自主访问,强制访问)的有前景的代替受到广泛的关注.在RBAC中,权限与角色相关联,用户通过成为适当角色的成 ...

  7. Opencv 编译

    转载 https://www.cnblogs.com/xinxue/p/5766756.html OpenCV 3.4 版本,圣诞节前发布了,该版本新增了一种去掉视频背景的算法,dnn 模块的进一步改 ...

  8. CSS弹性盒模型flex概念

    盒模型分为:标准w3c盒模型.IE盒模型.以及css中的伸缩盒模型. 先说CSS的伸缩盒模型:flex模型是CSS3引入的新的布局模型,是flexible box的缩写,一般称之为弹性盒模型.和CSS ...

  9. Base64就是一种 基于64个可打印字符来表示二进制数据的表示方法

    Base64编码是从二进制到字符的过程. Base64编码主要用在传输.存储.表示二进制等领域,还可以用来加密,但是这种加密比较简单. byte[] byteArray = Encoding.UTF8 ...

  10. 使用xshell连接本地虚拟机中的Linux问题

    xshell 连接虚拟机中Linux报错: Could not connect to '192.168.8.120' (port 22):Connection failed. 原因:虚拟机中Linux ...