传送门:>Here<

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

解题思路

不免要吐槽一下这题的数据,久调一下午无果与标程对拍没有任何差错不知道为什么就是WA 既然极限数据已经和标程拍上了那么权当出了吧……

不过还是一道好题

首先考虑这道题暴力的做法——将每条边作为新图的点,然后枚举原图的点,遍历一遍这个点相邻的所有边,按照大小打擂在新图中连边,但是这样边的数量多达$M^2$

可以考虑优化边的数量,用到差分的思想——以其中一条边作为基准,往上走要加,往下走不加。作为基准的这一条边也就是当前路径的入边,至于出边,只需要沿着差分的边走就可以了。于是我们所需要做的就是将每个点相邻的所有边排序,并且相邻的连边——大的往小的权值为0,小的往大的权值为差值。并且对于每一条边,它的反向边应当与它连一条权值为其本身的边,作为基准嘛

Code

/*By DennyQi 2018.8.11*/
#include <cstdio>
#include <queue>
#include <cstring>
#include <algorithm>
#define  r  read()
#define  lr lread()
#define  Max(a,b)  (((a)>(b)) ? (a) : (b))
#define  Min(a,b)  (((a)<(b)) ? (a) : (b))
using namespace std;
typedef long long ll;
;
;
const int INF = 1e18;
inline int read(){
    ; ; register int c = getchar();
    ')) c = getchar();
    , c = getchar();
    ) + (x << ) + c - ', c = getchar(); return x * w;
}
inline int lread(){
    ll x = ; ; register int c = getchar();
    ')) c = getchar();
    , c = getchar();
    ) + (x << ) + c - ', c = getchar(); return x * w;
}
struct Edge{
    ll len;
    int idx;
}e[MAXM];
struct Dij{
    ll w;
    int idx;
};
inline bool operator < (const Dij& a, const Dij& b){
    return a.w > b.w;
}
int N,M,x,y,S,T,v,top;
;
ll pcost[MAXM],cost[MAXM],z;
;
ll d[MAXM];
bool vis[MAXM];
priority_queue <Dij> q;
inline bool comp(const Edge& a, const Edge& b){
    return a.len < b.len;
}
inline void add(int u, int v, int w){
//    printf("%lld->%lld(%lld)\n",u,v,w);
    to[++num_edge] = v;
    cost[num_edge] = w;
    nxt[num_edge] = first[u];
    first[u] = num_edge;
}
inline void padd(int u, int v, int w){
    pto[++pnum_edge] = v;
//    printf("num(%lld): %lld->%lld(%lld)\n",pnum_edge,u,v,w);
    pcost[pnum_edge] = w;
    pnxt[pnum_edge] = pfirst[u];
    pfirst[u] = pnum_edge;
    ){
        add(S, pnum_edge, w);
    }
    if(v == N){
        add(pnum_edge, T, w);
    }
}
inline void Dijkstra(int s){
    ; i <= T; ++i) d[i] = INF;
    d[s] = ;
    q.push((Dij){,s});
    ll u,v;
    while(!q.empty()){
        u = q.top().idx; q.pop();
        if(vis[u]) continue;
        vis[u] = ;
        ; i = nxt[i]){
            v = to[i];
            if(d[u] + cost[i] < d[v]){
                d[v] = d[u] + cost[i];
                q.push((Dij){d[v],v});
            }
        }
    }
}
int main(){
//    freopen(".in","r",stdin);
//    freopen("qxz.out","w",stdout);
    N = r, M = r;
    memset(pfirst,-,sizeof(pfirst));
    memset(first,-,sizeof(first));
    S = M*+;
    T = M*+;
//    printf("S = %lld  T = %lld\n",S,T);
    ; i <= M; ++i){
        x = r, y = r, z = lr;
        padd(x, y, z);
        padd(y, x, z);
    }
    int v;
    ; x < N; ++x){
        top = ;
        ; i = pnxt[i]){
            e[++top] = (Edge){pcost[i], i};
        }
        sort(e+,e+top+,comp);
        ; i <= top; ++i){
            if(i < top){
                add(e[i].idx, e[i+].idx, e[i+].len-e[i].len);
            }
            ){
                add(e[i].idx, e[i-].idx, );
            }
            add(e[i].idx^, e[i].idx, e[i].len);
        }
    }
    Dijkstra(S);
    printf("%lld", d[T]);
    ;
}

[PA2012] Tax的更多相关文章

  1. 「BZOJ 4289」 PA2012 Tax

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

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

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

  3. BZOJ4289 : PA2012 Tax

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

  4. bzoj 4289: PA2012 Tax

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

  5. ●BZOJ 4289 PA2012 Tax

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

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

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

  7. 【刷题】BZOJ 4289 PA2012 Tax

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

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

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

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

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

随机推荐

  1. centos7下zabbix安装与部署

    1.Zabbix介绍 zabbix是一个基于WEB界面的提供分布式系统监视以及网络监视功能的企业级的开源解决方案. zabbix能监视各种网络参数,保证服务器系统的安全运营:并提供灵活的通知机制以让系 ...

  2. pip3 升级失败的解决方法!亲测有效

    pip3 --default-timeout=10000 install -U pip 注意:由于防火长城的存在,会导致更新失败,如果你加上--default-timeout=10000  这个就ok ...

  3. 使用matplotlib画饼图

    import matplotlib.pyplot as pltx = [4, 9, 21, 55, 30, 18]labels = ['math', 'history', 'chemistry', ' ...

  4. Vue2 实现树形菜单(多级菜单)功能模块

    结构示意图 ├── index.html ├── main.js ├── router │ └── index.js # 路由配置文件 ├── components # 组件目录 │ ├── App. ...

  5. django 路由系统,数据库操作

    一.修改配置 数据库 DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME':'dbname', 'USER': ...

  6. Python之字符串格式化

    1)     占位符%s: %s是通用的占位符,所有类型不管是string还是int还是float全都代表. 如果使用%d,则只能代表整数:如果是%f,则只能代表小数: 2)     直接用加号+连接 ...

  7. Java 数据库操作

    目录 Java数据库组织架构 下载驱动包 连接数据库 连接数据库的三个步骤 连接数据库的高开销 Statement接口介绍 PreparedStatement类 使用PreparedStatement ...

  8. vue-lazyload简单使用

    vue-lazyload简单使用 npm地址:https://www.npmjs.com/package/vue-lazyload github地址:https://github.com/hilong ...

  9. 认识Debian

    Debian -- 通用操作系统https://www.debian.org/ DebianStretch - Debian Wikihttps://wiki.debian.org/DebianStr ...

  10. html js 表单提交前检测数据

    通过使用form的onsibmit来控制是否提交数据 返回值为真是提交,其他不变,示例如下: JS部分 function check() { var newPwd = document.getElem ...