Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 755  Solved: 240
[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

这题居然卡long long,也是没谁了

首先一个很显然的思路是暴力拆边

即把每个点每一条入边和每一条出边的两两看做一个点,权值为两边的较大值

但是这样很显然是$O(m^2)$,肯定会GG

所以我们考虑一种神仙操作。

对于一条无向边,我们把它看成两条有向边

然后我们这样构图

1.对于一个点,我们把它的出边从小到大排序

2.枚举每一条边,如果这条边连接着1或者N,那么我们从S连向这条边或者从这条边连向T,权值为该边的权值

3.从改边所对应的入边向该边连一条边,边权为它们的权值

4.枚举每一条出边,从权值较小的向权值较大的连权值为两边差值的边,从权值较大的向权值较小的连权值为0的边

可能这样说不是很清楚,借鉴一下这位大佬的图

#include<cstdio>
#include<algorithm>
#include<queue>
#include<cstring>
#define Pair pair<long long,int>
#define F first
#define S second
const int MAXN=*1e6+;
using namespace std;
inline int read()
{
char c=getchar();int x=,f=;
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){x=x*+c-'';c=getchar();}
return x*f;
}
struct Edge
{
int u,v,w,nxt;
}E[MAXN];
int headE[MAXN],numE=;
inline void add_edge(int x,int y,int z)
{
E[numE].u=x;
E[numE].v=y;
E[numE].w=z;
E[numE].nxt=headE[x];
headE[x]=numE++;
}
struct node
{
int u,v,w,nxt;
}edge[MAXN];
int head[MAXN],num=;
inline void AddEdge(int x,int y,int z)
{
edge[num].u=x;
edge[num].v=y;
edge[num].w=z;
edge[num].nxt=head[x];
head[x]=num++;
}
int N,M,S,T;
int temp[MAXN];
long long dis[MAXN];
bool vis[MAXN];
void Dijstra()
{
memset(dis,0xf,sizeof(dis));dis[S]=;
priority_queue<Pair>q;
q.push(make_pair(,S));
while(q.size()!=)
{
while(vis[q.top().second]&&q.size()>) q.pop();
long long p=q.top().second;
vis[p]=;
for(int i=head[p];i!=-;i=edge[i].nxt)
if(dis[edge[i].v]>dis[p]+edge[i].w)
dis[edge[i].v]=dis[p]+edge[i].w,
q.push(make_pair(-dis[edge[i].v],edge[i].v));
}
printf("%lld\n",dis[T]);
}
int comp(const int &a,const int &b)
{
return E[a].w<E[b].w;
}
int main()
{
#ifdef WIN32
freopen("a.in","r",stdin);
#else
#endif
memset(headE,-,sizeof(headE));
memset(head,-,sizeof(head));
N=read();M=read();S=,T=*(M+);
for(int i=;i<=M;i++)
{
int x=read(),y=read(),z=read();
add_edge(x,y,z);
add_edge(y,x,z);
}
for(int i=;i<=N;i++)
{
int tempnum=;
for(int j=headE[i];j!=-;j=E[j].nxt)
temp[++tempnum]=j;
sort(temp+,temp+tempnum+,comp);
for(int j=;j<=tempnum;j++)
{
int x=temp[j],y=temp[j+];
if(E[x].u==)
AddEdge(S,x,E[x].w);
if(E[x].v==N)
AddEdge(x,T,E[x].w);
AddEdge(x^,x,E[x].w);
if(j!=tempnum)
AddEdge(x,y,E[y].w-E[x].w),
AddEdge(y,x,);
}
}
Dijstra();
return ;
}

BZOJ 4289: 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 PA2012 Tax

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

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

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

  4. bzoj 4289 PA2012 Tax——构图

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

  5. bzoj 4289: PA2012 Tax

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

  6. 【刷题】BZOJ 4289 PA2012 Tax

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

  7. BZOJ 4289: PA2012 Tax Dijkstra + 查分

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

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

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

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

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

随机推荐

  1. BZOJ 4028 分块

    zrt当年是怎么想到的--. 思路: 考虑把序列分块 对于每块 存xor[i] 表示从本块开头到i的前缀异或和 把它扔进set里 存gcd[i]表示从本块开头到i的前缀gcd. 如果这一块的GCD和整 ...

  2. Unity3D项目

    Input.mousePosition //鼠标点击的位置 0 左键  1右键  2滚轮 Input.GetMouseButton(0) //当鼠标左键处于按下状态的时候返回True Input.Ge ...

  3. canvas绘制三等分饼型图

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  4. 关于Java中equal函数和==的一些区别

    equal函数比较的到底是什么,很明显是比较的值,但是什么值?与==比较的堆中的内存地址不同,其比较的是对象的值,包括各个属性的值.我们在重新overriding此方法时首先要判断是否为同一对象,如果 ...

  5. SQL学习——基础语句(3)

    先上数据表 student表 grade 表 SQL Union 语句 合并两个或多个select查询结果集. select s_id from student union select  s_id ...

  6. Hibernate框架学习(五)——批量查询(概述)

    一.HQL查询(Hibernate Query Language)多表查询,但不复杂时使用 Hibernate独家查询语言,属于面向对象的查询语言 1.基本查询 2.条件查询 注意:HQL语句中不可能 ...

  7. Html5必看:教你如何选择移动APP开发框架

    如何选择移动APP开发框架一直是困扰很多新手的难题,今天杭州APP开发小编就和大家一起分享一下HTML5 移动app开发过程中框架该如何选择?当然我们得先从下面几个方面来评估一个框架的优越性,然后再做 ...

  8. AC Codeforces Round #499 (Div. 2) E. Border 扩展欧几里得

    没想出来QAQ....QAQ....QAQ.... 对于一般情况,我们知道 ax+by=gcd(a,b)ax+by=gcd(a,b)ax+by=gcd(a,b) 时方程是一定有解的. 如果改成 ax+ ...

  9. Python基础数据类型list,tuple

    列表是有序的可变的元素集合.列表中的每个元素可以使任何数据类型,包括列表本身. 列表生成 Python3中的列表通过定义,for循环,列表推导式等几种方式生成 定义 直接通过中括号`[]`定义一个列表 ...

  10. BZOJ 2342 [SHOI2011]双倍回文 (回文自动机)

    题目大意:略 先建出$PAM$ 因为双倍回文串一定是4的倍数,所以找出$PAM$里所有$dep$能整除4的节点 看这个串是否存在一个回文后缀,长度恰好为它的一半,沿着$pre$链往上跳就行了 暴跳可能 ...