题意

多组样例

给定\(n,m,a,b,c\),给定一个长度为\(m\)的数组\(p[]\),给定\(m\)条边,构成一个\(n\)个点\(m\)条边的无向图,\(Mike\)想要从\(a\)走到\(b\),再从\(b\)走到\(c\),你可以在他从\(a\)出发前将\(p[]\)中的值分配到\(m\)条边上,问\(Mike\)最少走多少路程

分析

我们先将所有边的权值赋为\(1\),意为两点间的最小边数为多少

如果\(a\)到\(b\)和\(b\)到\(c\)的最短路不重合,那就直接将两条路上的边从小到大赋值即可,问题在于有重合的部分路径

发现\(\sum n\leq 2\cdot 10^5\),我们可以枚举重合的点\(i\),让\(Mike\)走路径\(a->i->b->i->c\),然后求得边数,其中\(i->b\)的路径为\(p[]\)中最小的几个元素,因为要走两遍,\(i->a\)和\(i->c\)的的路径为剩下元素中最小的元素

由于为无向图,\(i\)到三点距离即为三点到\(i\)距离,为表述方便,皆用\(i\)到三点表述

枚举\(i\)肯定不能以\(i\)为起点求最短路,否则时间复杂度太高,则可以以三点求最短路,然后枚举\(i\)

先计算\(i->a\)的边数,以\(a\)为起点,使用\(Dijkstra\)算法,再计算\(i->b\)的边数,以\(b\)为起点,使用\(Dijkstra\)算法,再计算\(i->c\)的边数,以\(c\)为起点,使用\(Dijkstra\)算法,其中不同的距离设为\(disa[],disb[],disc[]\)

因为是求路径权值和,可直接排序后计算前缀和\(sum[]\)

设\(i->a\)的路径为\(disai\),\(i->\)的b路径为\(disbi\),\(i->c\)的路径为\(disci\),则答案为\(sum[disai + disbi + disci] + sum[disbi]\)的最小值(三边总的前缀和加上\(i->b\)的二次计算)

由于\(i\)到三点的路径不可能有重叠(否则取重叠点可使得答案更小),因此三条路径和小于\(m\),正好使得\(disai + disbi + disci\)不会超出\(sum[]\)的范围

#pragma GCC optimize(3, "Ofast", "inline")

#include <bits/stdc++.h>

#define start ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define ll long long
#define int ll
#define ls st<<1
#define rs st<<1|1
#define pii pair<int,int>
#define rep(z, x, y) for(int z=x;z<=y;++z)
#define com bool operator<(const node &b)
using namespace std;
const int maxn = (ll) 2e5 + 5;
const int mod = (ll) 1e9 + 7;
const int inf = 0x3f3f3f3f;
int T = 1; struct edge {
int v, next, w;
} e[maxn << 1]; struct node {
int dis, u; bool operator<(const node &b) const {
return dis > b.dis;
}
}; int cnt;
int head[maxn];
int disa[maxn];
int disb[maxn];
int disc[maxn];
bool vis[maxn]; void addedge(int u, int v, int w) {
e[++cnt].next = head[u];
e[cnt].v = v;
e[cnt].w = w;
head[u] = cnt;
e[++cnt].next = head[v];
e[cnt].v = u;
e[cnt].w = w;
head[v] = cnt;
} int n, m, s; void dijkstra_a() {
priority_queue<node> q;
disa[s] = 0;
node st;
st.dis = 0;
st.u = s;
q.push(st);
while (!q.empty()) {
node u = q.top();
q.pop();
if (vis[u.u])
continue;
vis[u.u] = true;
for (int i = head[u.u]; ~i; i = e[i].next) {
int v = e[i].v;
if (disa[v] > disa[u.u] + e[i].w) {
disa[v] = disa[u.u] + e[i].w;
node w;
w.dis = disa[v];
w.u = v;
q.push(w);
}
}
}
} void dijkstra_b() {
priority_queue<node> q;
disb[s] = 0;
node st;
st.dis = 0;
st.u = s;
q.push(st);
while (!q.empty()) {
node u = q.top();
q.pop();
if (vis[u.u])
continue;
vis[u.u] = true;
for (int i = head[u.u]; ~i; i = e[i].next) {
int v = e[i].v;
if (disb[v] > disb[u.u] + e[i].w) {
disb[v] = disb[u.u] + e[i].w;
node w;
w.dis = disb[v];
w.u = v;
q.push(w);
}
}
}
} void dijkstra_c() {
priority_queue<node> q;
disc[s] = 0;
node st;
st.dis = 0;
st.u = s;
q.push(st);
while (!q.empty()) {
node u = q.top();
q.pop();
if (vis[u.u])
continue;
vis[u.u] = true;
for (int i = head[u.u]; ~i; i = e[i].next) {
int v = e[i].v;
if (disc[v] > disc[u.u] + e[i].w) {
disc[v] = disc[u.u] + e[i].w;
node w;
w.dis = disc[v];
w.u = v;
q.push(w);
}
}
}
} int num[maxn], sum[maxn]; void solve() {
memset(head, -1, sizeof(head));
cnt = 0;
int a, b, c;
cin >> n >> m >> a >> b >> c;
rep(i, 1, m)cin >> num[i];
sort(num + 1, num + 1 + m);
rep(i, 1, m)sum[i] = sum[i - 1] + num[i];
rep(i, 1, m) {
int u, v;
cin >> u >> v;
addedge(u, v, 1);
}
s = a;
rep(i, 1, n) {
disa[i] = disb[i] = disc[i] = inf;
vis[i] = false;
}
dijkstra_a();
s = b;
rep(i, 1, n)vis[i] = false;
dijkstra_b();
s = c;
rep(i, 1, n)vis[i] = false;
dijkstra_c();
int ans = LLONG_MAX;
rep(i, 1, n) {
int disai = disa[i];
int disbi = disb[i];
int disci = disc[i];
if (disai + disbi + disci > m)
continue;
int now = sum[disai + disbi + disci] + sum[disbi];
ans = min(ans, now);
}
cout << ans << '\n';
} signed main() {
start;
cin >> T;
while (T--)
solve();
return 0;
}

CodeForces 1343E Weights Distributing的更多相关文章

  1. 【codeforces 496E】Distributing Parts

    [题目链接]:http://codeforces.com/contest/496/problem/E [题意] 给你n个歌曲; 每个歌曲有一个需要声音的区间li,ri; 然后给你m个人; 每个人也有一 ...

  2. codeforces 496 E. Distributing Parts(贪心+set二分)

    题目链接:http://codeforces.com/contest/496/problem/E 题意:有n场演出,每场演出都有限制的高音和低音.然后m个人给出每个人的极限高音和低音还有出场次数. 最 ...

  3. CF #636 (Div. 3) 对应题号CF1343

    unrated 选手悠闲做题,然后只做出四个滚蛋了 符合 div3 一贯风格,没啥难算法 E最后就要调出来了,但还是赛后才A的 CF1343A Candies 传送门 找到一个 \(x\),使得存在一 ...

  4. [codeforces 339]C. Xenia and Weights

    [codeforces 339]C. Xenia and Weights 试题描述 Xenia has a set of weights and pan scales. Each weight has ...

  5. codeforces 339C Xenia and Weights(dp或暴搜)

    转载请注明出处: http://www.cnblogs.com/fraud/          ——by fraud Xenia and Weights Xenia has a set of weig ...

  6. Codeforces 1079 E - The Unbearable Lightness of Weights

    E - The Unbearable Lightness of Weights 思路: 分组背包dp 每组最多只能选一个 一些优化可以快很多 代码: #pragma GCC optimize(2) # ...

  7. Codeforces Round #283 (Div. 2) E. Distributing Parts 贪心+set二分

    E. Distributing Parts time limit per test 2 seconds memory limit per test 256 megabytes input standa ...

  8. [Codeforces 496E] Distributing Parts

    [题目链接] https://codeforces.com/contest/496/problem/E [算法] 按右端点排序 , 每个乐曲优先选取的左端点最大的演奏家 用std :: set维护贪心 ...

  9. codeforces 497c//Distributing Parts// Codeforces Round #283(Div. 1)

    题意:有n个区间[ai,bi],然后有n个人落在[ci,di],每个人能用ki次.问一种方式站满n个区间. 两种区间都用先x后y的升序排序.对于当前的区间[ai,bi],将ci值小于当前ai的全部放入 ...

  10. CodeForces 339C Xenia and Weights(暴力求解DFS)

    题意:给定 1-10的某几种砝码,给定的每种有无穷多个,然后放 m 个在天平上,要满足,相邻的两次放的砝码不能是同一种,然后是在天平两端轮流放,并且放在哪一个托盘上,那么天平必须是往哪边偏. 析:这个 ...

随机推荐

  1. Spring源码:Bean生命周期(终章)

    前言 本系列前面讲解了Spring的bean定义.bean实例化.bean初始化等生命周期.这些步骤使我们能够了解bean从创建到准备好使用所经历的过程.但是,除了这些步骤,bean的销毁也是非常重要 ...

  2. vue3+vite2+element-plus+ts搭建一个项目

    花了几天用 vue3+ vite2+ element-plus+ ts 搭了个 极简版骨架型数据管理系统,使用静态数据模拟动态路由,路由拦截,登录页面鉴权等,使用了iconify字体图标,整合了ces ...

  3. 用go封装一下封禁功能

    用go封装一下封禁功能 本篇为用go设计开发一个自己的轻量级登录库/框架吧 - 秋玻 - 博客园 (cnblogs.com)的封禁业务篇,会讲讲封禁业务的实现,给库/框架增加新的功能. 源码:http ...

  4. Linux,会这些就够了

    在测试当中,其实对Linux的要求不高,我们在工作中需要记住常用的一些命令,不常用的实际用到的时候再查在记即可,最重要我们要使用命令可以查看日志,定位bug   目录篇: 可用  pwd  命令查看用 ...

  5. 常见 Linux 提权

    Common Linux Privesc 记录 常见 Linux 提权的 提权方式:水平提权,垂直提权. 水平提权:这是您通过接管与您处于相同权限级别的不同用户来扩大您对受感染系统的影响的地方. 例如 ...

  6. hugp-MemE关键美化

    配置front matter 使用vscode snippet快捷生成front matter 参考博客:vs-code-workflows-for-hugo. markdown-snippets-n ...

  7. C++面试八股文:std::vector和std::list,如何选择?

    某日二师兄参加XXX科技公司的C++工程师开发岗位第24面: 面试官:list用过吗? 二师兄:嗯,用过. 面试官:请讲一下list的实现原理. 二师兄:std::list被称为双向链表,和C中手写双 ...

  8. Linux系统运维之FastDFS集群部署

    一.简介 FastDFS是一个开源的轻量级分布式文件系统,它对文件进行管理,功能包括:文件存储.文件同步.文件访问(文件上传.文件下载)等,解决了大容量存储和负载均衡的问题.FastDFS服务端有两个 ...

  9. FFmpeg合并视频和音频文件

    使用IDM下载Bilibili的视频会出现音视频分离的问题,通常文件大的是视频(没有声音),文件小的是单独的音频. 将两个文件都下载下来后,可以使用FFmpeg将其合并成一个视频文件.首先去FFmpe ...

  10. Mysql基础篇(三)之多表查询

    一. 多表关系 一对多(多对一) 多对一 一对一 1. 一对多 (1). 案例:部门与员工的关系 (2). 关系:一个部门对应多个员工,一个员工对应一个部门 (3). 实现:在多的一方建立外建,指向一 ...