Description

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

Input

Output

那个取最大值的操作十分烦人,考虑如何将这个判断去掉.
可以用查分的方式:如果进来的边是小的,那么从大的边出去就要补齐差值.
补齐差值就直接连一条差值为 $d$ 的边即可.
然后跑一个 $Dijkstra$ 即可.

#include <cstdio>
#include <queue>
#include <algorithm>
#include <cstring>
#include <map>
#define N 400003
#define inf 10000000000000
#define ll long long
#define setIO(s) freopen(s".in","r",stdin)
using namespace std;
namespace IO
{
char *p1, *p2, buf[100000]; #define nc() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 100000, stdin), p1 == p2) ? EOF : *p1 ++ ) int rd() {
int x = 0, f = 1;
char c = nc();
while (c < 48) {
if (c == '-')
f = -1;
c = nc();
}
while (c > 47) {
x = (((x << 2) + x) << 1) + (c ^ 48), c = nc();
}
return x * f;
}
};
struct Edge
{
int to,dis;
Edge(int to=0,int dis=0):to(to),dis(dis){}
};
vector<Edge>G[N];
bool cmp(Edge a,Edge b)
{
return a.dis<b.dis;
}
map<int,int>id[N];
int n,m,cnt,edges,s,t;
int hd[N*6],nex[N*6],to[N*6],done[N*6];
ll d[N*6],val[N*6];
inline void addedge(int u,int v,int c)
{
nex[++edges]=hd[u],hd[u]=edges,to[edges]=v,val[edges]=1ll*c;
}
struct Node
{
ll dis;
int u;
Node(ll dis=0,int u=0):dis(dis),u(u){}
bool operator<(Node b) const
{
return dis>b.dis;
}
};
priority_queue<Node>q;
inline void Dijkstra()
{
int i;
for(i=0;i<=t;++i) d[i]=inf, done[i]=0;
d[s]=0, q.push(Node(0,s));
while(!q.empty())
{
Node e=q.top();q.pop();
if(done[e.u]) continue;
done[e.u]=1;
int u=e.u;
for(i=hd[u];i;i=nex[i])
{
int v=to[i];
if(d[u]+val[i]<d[v])
{
d[v]=d[u]+val[i];
q.push(Node(d[v],v));
}
}
}
}
int main()
{
int i,j;
// setIO("input");
n=IO::rd(),m=IO::rd();
for(i=1;i<=m;++i)
{
int a=IO::rd(),b=IO::rd(),c=IO::rd();
G[a].push_back(Edge(b,c)), G[b].push_back(Edge(a,c));
}
for(i=1;i<=n;++i)
{
sort(G[i].begin(),G[i].end(),cmp);
if(G[i].empty()) continue;
id[i][G[i][0].dis]=++cnt;
for(j=1;j<(int)G[i].size();++j) if(G[i][j].dis!=G[i][j-1].dis) id[i][G[i][j].dis]=++cnt;
}
for(i=1;i<=n;++i)
{
int k,lst=0,pre=0;
for(k=0;k<(int)G[i].size();k=j+1)
{
j=k;
int cur=id[i][G[i][j].dis];
while(j<(int)G[i].size()-1&&G[i][j+1].dis==G[i][j].dis) ++j;
if(lst) addedge(cur,lst,0), addedge(lst,cur,G[i][k].dis-pre);
for(int o=k;o<=j;++o) addedge(cur, id[G[i][o].to][G[i][o].dis], G[i][o].dis);
lst=cur, pre=G[i][k].dis;
}
}
s=0, t=cnt+2;
for(i=0;i<G[1].size();++i) if(i==0||G[1][i].dis!=G[1][i-1].dis) addedge(s,id[1][G[1][i].dis],G[1][i].dis);
for(i=0;i<G[n].size();++i) if(i==0||G[n][i].dis!=G[n][i-1].dis) addedge(id[n][G[n][i].dis],t,0);
Dijkstra(), printf("%lld\n",d[t]);
return 0;
}

  

BZOJ 4289: PA2012 Tax Dijkstra + 查分的更多相关文章

  1. BZOJ.4289.PA2012 Tax(思路 Dijkstra)

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

  2. bzoj 4289: PA2012 Tax

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

  3. ●BZOJ 4289 PA2012 Tax

    ●赘述题目 算了,题目没有重复的必要. 注意理解:对答案造成贡献的是每个点,就是了. 举个栗子: 对于如下数据: 2 1 1 2 1 答案是 2: ●题解 方法:建图(难点)+最短路. 先来几个链接: ...

  4. 【刷题】BZOJ 4289 PA2012 Tax

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

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

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

  6. bzoj 4289 PA2012 Tax——构图

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4289 可以把一个点上的边按权值排序,然后边权小的向第一个比它大的连差值的边,边权大的向第一个 ...

  7. BZOJ 4289: PA2012 Tax(最短路)

    Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 755  Solved: 240[Submit][Status][Discuss] Descriptio ...

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

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

  9. 「BZOJ 4289」 PA2012 Tax

    「BZOJ 4289」 PA2012 Tax 题目描述 给出一个 \(N\) 个点 \(M\) 条边的无向图,经过一个点的代价是进入和离开这个点的两条边的边权的较大值,求从起点 \(1\) 到点 \( ...

随机推荐

  1. 注解@Slf4j的作用

    lombok.extern.slf4j 代码: @Slf4j public class LogExample { } 产生以下代码: public class LogExample { private ...

  2. mysql——单表查询——聚合函数——概念

    使用聚合函数查询 group by关键字通常和聚合函数一起使用 .count()函数 count()函数用来统计记录的条数 举例:使用count()函数统计employee表的记录数 select c ...

  3. 执行python程序 出现三部曲

    1.执行一个python程序 ,会产生一个进程 ,然后会在内存生成一份内存空间 先把python解释器代码加载到内存里, python解释器代码就是C语言代码 2. 然后再把 自己写的python文件 ...

  4. String,StringBuffer,StringBulider 三者的区别

    1.String 是字符串常量,StringBuffer 和StringBuilder 是字符串变量. 2.运行速度 StringBuilder > StringBuffer > Stri ...

  5. Hive Error : Java heap space 解决方案

    Java heap space问题一般解决方案: 设置 set io.sort.mb=10; 排序所使用的内存数量,默认值是100M,和mapred.child.java.opts相对应,opts默认 ...

  6. Vue.js官方文档学习笔记(二)组件化应用的构建

    组件化应用的构建 组件化应用允许我们使用小型.独立和通常可复用的组件构建大型应用. Vue注册组件 Vue.component('todo-item',{template:'<li>这是个 ...

  7. Linux免密登陆设置了免密登陆为啥还需要输入密码

    一.设置了免密码登陆但是还是需要输入密码: 权限保证:1.authorized-keys 的权限为 600 2.home.账户所在的目录如hadoop..ssh这三个文件的权限都必须设置为700,缺少 ...

  8. logging模块及日志框架

    logging模块及日志框架 logging模块 一.导入方式 import logging 二.作用 写日志 三.模块功能 3.1 经常使用 # V1 import logging logging ...

  9. Jquery复习(七)之尺寸

    jQuery 尺寸 方法 jQuery 提供多个处理尺寸的重要方法: width() height() innerWidth() innerHeight() outerWidth() outerHei ...

  10. 运维LVS-NAT模式理解

    一.LVS-NAT模式的工作原理这个是通过网络地址转换的方法来实现调度的.首先调度器(LB)接收到客户的请求数据包时(请求的目的IP为VIP),根据调度算法决定将请求发送给哪个 后端的真实服务器(RS ...