【Educational Codeforces Round 38】D. Buy a Ticket 堆优化Dijkstra

题意

给定一张无向图,对每个点$i\in S$求$\min_{j\in S} {2\times d(i,j)+a_j}$



考虑多源多汇最短路会超时,换个角度考虑每个$j$,如果$j=i$,那么答案为$a_i$,如果有更优的方案,那么为$i$到$j$的一条路径加上$a_j$,将这个过程看成两条路径,并且将$a_j$独立为一条路径,就得到最短路算法中的松弛操作,可以建立一个超级源点,连向各点,边权为$a_i$,那么从源点跑一遍最短路之后就是每个点所求答案

时间复杂度$O(n\log n)$

代码

#include <bits/stdc++.h>
#define inf 0x7f7f7f7f
using namespace std;
typedef long long LL;
typedef pair<LL, int> pli;
const int N = 200010;
int cnt, head[N], nxt[3 * N], to[3 * N];
LL val[3 * N];
inline void add_edge(int u, int v, LL w) {
    to[cnt] = v; val[cnt] = w; nxt[cnt] = head[u]; head[u] = cnt++;
}
int vis[N];
LL dis[N];
int n, m, x, y;
LL z;
inline void dijkstra(int s) {
    priority_queue<pli, vector<pli >, greater<pli > > pq;
    memset(vis, 0, sizeof(vis));
    memset(dis,0x3f,sizeof(dis)); dis[s] = 0;
    pq.push(make_pair(dis[s], s));
    while(!pq.empty()) {
        pli now = pq.top(); pq.pop();
        int u = now.second; if(vis[u]) continue; vis[u] = 1;
        for(int i = head[u]; ~i; i = nxt[i]) {
            int v = to[i];
            if(dis[v] > dis[u] + val[i]) {
                dis[v] = dis[u] + val[i];
                pq.push(make_pair(dis[v], v));
            }
        }
    }
}
int main() {
    cnt = 0; memset(head, -1, sizeof(head));
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= m; ++i) {
        scanf("%d%d%I64d", &x, &y, &z);
        add_edge(x, y, 2 * z); add_edge(y, x, 2 * z);
    }
    for(int i = 1; i <= n; ++i) {
        scanf("%I64d", &z);
        add_edge(0, i, z);
    }
    dijkstra(0);
    for(int i = 1; i <= n; ++i) {
        printf("%I64d%c", dis[i], i == n ? '\n' : ' ');
    }
    return 0;
}

原文地址:https://www.cnblogs.com/ogiso-setsuna/p/8455400.html

时间: 2024-10-03 00:39:09

【Educational Codeforces Round 38】D. Buy a Ticket 堆优化Dijkstra的相关文章

Educational Codeforces Round 38 (Rated for Div. 2) ----D

D. Buy a Ticket 问题转换为对于每一个点x,求出一个点y,使得xy的最短路2倍+在y举办的费用最小. 考虑建一个超级源点,向每一个点连一条费用为其举办所需费用,并且原图中的边权值*2,跑一遍最短路,每一个点到超级源点的最短路即为答案. 卡spfa,请用dijkstra. 1 #include<bits/stdc++.h> 2 #define LL long long 3 using namespace std; 4 const int inf=2e5+10; 5 int n,m;

Educational Codeforces Round 38 (Rated for Div. 2) ----C

C. Constructing Tests 经过简单的分析之后,我们可以发现,对于x,我们要求的就是一组n,m满足n^2-(n/m)^2=x. 有两种求法. 第一种: 观察n的极限范围是多少,我们发现,对于相同的n,m越大,该式值就越大,x的范围是1e9,为了得到n最大是多少,我们尽可能的减小m的值,我们发现m=1时式子没有什么意义,特判即可,当m=2时,我们发现左边为3/4*n^2,也就是说n的范围是sqrt(x)级别的,枚举n判断是否存在m即可. 第二种:原式可以化为(n-(n/m))*(n

Educational Codeforces Round 21 G. Anthem of Berland(dp+kmp)

题目链接:Educational Codeforces Round 21 G. Anthem of Berland 题意: 给你两个字符串,第一个字符串包含问号,问号可以变成任意字符串. 问你第一个字符串最多包含多少个第二个字符串. 题解: 考虑dp[i][j],表示当前考虑到第一个串的第i位,已经匹配到第二个字符串的第j位. 这样的话复杂度为26*n*m*O(fail). fail可以用kmp进行预处理,将26个字母全部处理出来,这样复杂度就变成了26*n*m. 状态转移看代码(就是一个kmp

Educational Codeforces Round 23 F. MEX Queries(线段树)

题目链接:Educational Codeforces Round 23 F. MEX Queries 题意: 一共有n个操作. 1.  将[l,r]区间的数标记为1. 2.  将[l,r]区间的数标记为0. 3.  将[l,r]区间取反. 对每个操作,输出标记为0的最小正整数. 题解: hash后,用线段树xjb标记一下就行了. 1 #include<bits/stdc++.h> 2 #define ls l,m,rt<<1 3 #define rs m+1,r,rt<&l

Educational Codeforces Round 23 D. Imbalanced Array(单调栈)

题目链接:Educational Codeforces Round 23 D. Imbalanced Array 题意: 给你n个数,定义一个区间的不平衡因子为该区间最大值-最小值. 然后问你这n个数所有的区间的不平衡因子和 题解: 对每一个数算贡献,a[i]的贡献为 当a[i]为最大值时的 a[i]*(i-l+1)*(r-i+1) - 当a[i]为最小值时的a[i]*(i-l+1)*(r-i+1). 计算a[i]的l和r时,用单调栈维护.具体看代码,模拟一下就知道了. 然后把所有的贡献加起来.

Educational Codeforces Round 23 E. Choosing The Commander (trie)

题目链接: Educational Codeforces Round 23 E. Choosing The Commander 题意: 一共有n个操作. 1.  插入一个数p 2.  删除一个数p 3.  询问有多少个数 使得 x^p<l 题解: 对于前两种操作用01trie就能解决. 对于对三个操作,我们考虑在trie上搜索. 1.  当l的bit位是1时,那边bit位是p的字数全部的数都会小于l,(因为p^p=0) 2.  当l的bit为是0时,那边只能向bit位是p的子树中搜. 这样算下来

Educational Codeforces Round 22 E. Army Creation(主席树)

题目链接:Educational Codeforces Round 22 E. Army Creation 题意: 给你n个数和一个数k,然后有q个询问. 每个询问 有一个区间[l,r],问你这个区间内在满足每一种数不超过k的情况下,最大能选多少个数出来. 强制在线. 题解: 一看就要用到主席树,和主席数求区间内有多少不同的数的个数处理方法相同. 依次将每个数插入,当这个数出现的个数等于k了,就把最前面的那个数删掉. 然后询问就访问root[r]就行了. 第一次写完数据结构没有调试一遍过样例,一

Educational Codeforces Round 21 F. Card Game(网络流之最大点权独立集)

题目链接:Educational Codeforces Round 21 F. Card Game 题意: 有n个卡片,每个卡片有三个值:p,c,l; 现在让你找一个最小的L,使得满足选出来的卡片l<=L,并且所有卡片的p的和不小于k. 选择卡片时有限制,任意两张卡片的c之和不能为质数. 题解: 和hdu 1565 方格取数(2)一样,都是求最大点权独立集. 不难看出来,这题再多一个二分. 注意的是在构造二部图的时候,按照c值的奇偶性构造. 当c==1时要单独处理,因为如果有多个c==1的卡片,

Educational Codeforces Round 36 (Rated for Div. 2)

Educational Codeforces Round 36 (Rated for Div. 2) F. Imbalance Value of a Tree You are given a tree T consisting of n vertices. A number is written on each vertex; the number written on vertex i is ai. Let's denote the function I(x,?y) as the differ