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. AGC037 C Numbers on a Circle【思维】

    题目传送门 题意 这道题被某大佬改编拿来出成考试题,是长这个样子的: 好的,其实这才是真正的题意: 给定初始序列和最终序列,每次选择一个数变成自己和相邻2个数的和.问初始序列是否可以变为最终序列,若可 ...

  2. python 并发编程 基于gevent模块实现并发的套接字通信

    之前线程池是通过操作系统切换线程,现在是程序自己控制,比操作系统切换效率要高 服务端 from gevent import monkey;monkey.patch_all() import geven ...

  3. 多网卡的bond模式-把多个物理网卡绑定成一个逻辑上的网卡

    参考: 多网卡的7种bond模式原理 如何实现网卡bond

  4. 【转帖】国产x86处理器KX-6000发布

    国产最先进x86处理器KX-6000发布:8核3.0GHz 力压酷睿i5处理器 https://www.cnbeta.com/articles/tech/858981.htm 全网所有的网页都写错了 ...

  5. windows如何使用bat快速安装计划任务?

    关键词:windows定时任务,schtasks,at ,bat schtasks 部分转自: https://www.cnblogs.com/yumianhu/p/3710743.html at的详 ...

  6. python爬取天气后报网

    前言 大二下学期的大数据技术导论课上由于需要获取数据进行分析,我决定学习python爬虫来获取数据.由于对于数据需求量相对较大,我最终选择爬取 天气后报网,该网站可以查询到全国各地多年的数据,而且相对 ...

  7. C语言--浮点数

    在程序中使用浮点数 -- 浮点数的精确性有限 -- 在从c语言中float类型的精确度只到小数点的7位 -- 浮点数只能在一定范围内去相信它 -- 在有精确度高的要求下不要使用浮点数(在算钱的时候,误 ...

  8. C#杀进程与之之子进程

    using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using S ...

  9. git 版本回退方法

    ORIG_HEAD 某些操作,例如 merage / reset 会把 merge 之前的 HEAD 保存到 ORIG_HEAD 中,以便在 merge 之后可以使用 ORIG_HEAD 来回滚到合并 ...

  10. Android 一共有多少种动画?准确告诉你!

    Android 动画 Android 动画在开发中是不可或缺的功能,或者说是界面灵动的添加剂.那你是否总结过 Android 中总共为开发者提供了多少种方式的动画呢?今天就为大家总结归纳一下.   报 ...