题意

多组样例

给定\(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. 【GiraKoo】C++编译中常用的内置宏

    开源项目:https://girakoo.com/ 联系方式:girakoo@163.com 简介 针对不同的平台,很多头文件,函数名称,类型占用空间不一致. 为了保证跨平台可编译,经常需要在项目中使 ...

  2. nc工具利用

    c: 瑞士军刀/网络测评工具    将本地的cmd 权限移交到外网 nc工具:应用    本地cmd打开, 输入  nc -e cmd 远程ip  5577  #连接到远程ip的5577 远程cmd打 ...

  3. kubernetes(k8s)大白学习02:容器和docker基础、使用、架构学习

    一.什么是容器 容器简介 简单说:容器(container)就是计算机上的一个沙盒进程,它与计算机上的所有其它进程相隔离. 这种隔离是怎么做到的呢?它利用了内核提供的 namespace 和 cgro ...

  4. celery笔记二之建立celery项目、配置及几种加载方式

    本文首发于公众号:Hunter后端 原文链接:celery笔记二之建立celery项目.配置及几种加载方式 接下来我们创建一个 celery 项目,文件夹及目录如下: proj/__init__.py ...

  5. k8s实战案例之基于StatefulSet控制器运行MySQL一主多从

    1.前言 Pod调度运⾏时,如果应⽤不需要任何稳定的标示.有序的部署.删除和扩展,则应该使⽤⼀组⽆状态副本的控制器来部署应⽤,例如 Deployment 或 ReplicaSet更适合⽆状态服务需求, ...

  6. 2023-07-04:给定一个数组A, 把它分成两个数组B和C 对于数组A每个i位置的数来说, A[i] = B[i] + C[i] 也就是一个数字分成两份,然后各自进入B和C 要求B[i], C[i

    2023-07-04:给定一个数组A, 把它分成两个数组B和C 对于数组A每个i位置的数来说, A[i] = B[i] + C[i] 也就是一个数字分成两份,然后各自进入B和C 要求B[i], C[i ...

  7. (一)centos7下如何搭建Nginx和FastDFS文件管理-环境搭建

    一.关于FastDFS 1.FastDFS简介 FastDFS(Fast Distributed File System)是一个开源的分布式文件系统,旨在解决大规模文件存储和访问的问题,例如图片.音视 ...

  8. Redis设计

    目录 过期键删除策略 持久化 RDB AOF AOF重写 主从复制 完整重同步和部分重同步 哨兵Sentinel 哨兵对redis服务器集群的监听 执行者选举 故障转移 选择新的主服务器流程 过期键删 ...

  9. 信奥赛题1001:Hello,World!

    这个题实在是太简单的了,无法比喻,直接付代码! //c++ #include<bits/stdc++.h> using namespace std; int main() { cout&l ...

  10. sshpass快速登录远程主机:s2

    #!/bin/bash passwd= if [ $# -ne 1 ] then echo "$0 [31|37|61]" fi if command -v sshpass the ...