JZOJ 7377.欢乐豆
\(\text{Problem}\)
有一个有向完全图,所有的 \(u\) 到 \(v\) 的边权为 \(a_u\)
修改 \(m\) 此有向边边权,求最终图上两两点对的最短路之和
\(1\le n \le 10^5,1\le m \le 3000,1\le a_u \le 10^6\)
\(\text{Solution}\)
好题
如果没有修改边,那么 \(u\) 到任意一点的最短路为 \(a_u\)
有修改边,注意到 \(m\) 相对 \(n\) 很小,也就是说涉及的点很少,不妨称其为特殊点
显然特殊点个数最多为 \(O(m)\) 的,且特殊边也是 \(O(m)\) 的
考虑把特殊边连起来的点看成一个连通块(也就是视特殊边为无向边,把特殊点连起来)
我们导出这些特殊点构成的图,就是很多连通块的组成的图
这样再考虑两两点对间的最短路
无非分为特殊点到块内和到块外
\(1.\) 特殊点到块外就是特殊点到普通点和特殊点到不在此连通块内的特殊点
\(2.\) 特殊点到块内一定是特殊点到特殊点的最短路
先考虑 \(①\)
逐个考虑块内的点 \(x\) 到块外所有点的最短路
显然是此块内点 \(x\) 到此块内其它点 \(y\) 再到外面
即 \(dis(x,y)+a_y\) 的最小值
所以 \(①\) 贡献的最短路和为 \((n-cnt) \cdot min\)
再考虑 \(②\)
通过某种手段求出块内全源最短路,将这些 \(dis\) 加起来即可
有特殊边,有普通边,普通边是形如 \(a_u\) 的只和此端点有关
枚举起点,用线段树维护 \(dis\)
特殊边单点修改松弛,特殊边没被影响过的点用普通边松弛,这些点分散在多个区间,线段树上区间修改即可
然后就完成了,确实有点麻烦,但思路很清晰
\(\text{Code}\)
#include <cstdio>
#include <iostream>
#include <vector>
#include <algorithm>
#define ls (p << 1)
#define rs (ls | 1)
#define re register
using namespace std;
typedef long long LL;
const int N = 1e5 + 5;
const LL INF = 1e15;
int n, m, a[N], id[N], Q[N], cnt, tot, Tot, bz[N], h[N], H[N], color;
LL dis[N];
vector<int> d[N];
struct edge{int to, nxt, w;}e[N];
inline void add_edge(int x, int y, int z){e[++tot] = edge{y, h[x], z}, h[x] = tot;}
struct Edge{int to, nxt;}E[N];
inline void add_Edge(int x, int y){E[++Tot] = Edge{y, H[x]}, H[x] = Tot;}
struct node{int x; LL s;}b[N];
inline node Min(node a, node b){return (a.s <= b.s ? a : b);}
inline bool cmp(node a, node b){return a.s < b.s;}
inline void read(int &x)
{
x = 0; char ch = getchar(); int f = 1;
for(; !isdigit(ch); f = (ch == '-' ? -1 : f), ch = getchar());
for(; isdigit(ch); x = (x<<3) + (x<<1) + (ch^48), ch = getchar());
x *= f;
}
void dfs(int x)
{
bz[x] = color, Q[++cnt] = x;
for(re int i = H[x]; i; i = E[i].nxt) if (!bz[E[i].to]) dfs(E[i].to);
}
LL tag[N >> 1], Mn[N >> 1]; int Mp[N >> 1];
inline void pushup(int p)
{
if (Mn[ls] <= Mn[rs]) Mn[p] = Mn[ls], Mp[p] = Mp[ls];
else Mn[p] = Mn[rs], Mp[p] = Mp[rs];
}
void build(int p, int l, int r)
{
tag[p] = Mn[p] = INF;
if (l == r) return void(Mp[p] = l);
int mid = l + r >> 1;
build(ls, l, mid), build(rs, mid + 1, r), pushup(p);
}
inline void pushdown(int p)
{
if (tag[p] == INF) return;
if (Mn[ls] != INF + 1) Mn[ls] = min(Mn[ls], tag[p]), tag[ls] = min(tag[ls], tag[p]);
if (Mn[rs] != INF + 1) Mn[rs] = min(Mn[rs], tag[p]), tag[rs] = min(tag[rs], tag[p]);
tag[p] = INF;
}
void modify(int p, int l, int r, int tl, int tr, LL v)
{
if (tl > r || tr < l || v >= tag[p]) return;
if (tl <= l && r <= tr)
{
if (Mn[p] != INF + 1) Mn[p] = min(Mn[p], v), tag[p] = min(tag[p], v);
return;
}
pushdown(p);
int mid = l + r >> 1;
if (tl <= mid) modify(ls, l, mid, tl, tr, v);
if (tr > mid) modify(rs, mid + 1, r, tl, tr, v);
pushup(p);
}
void pushflag(int p, int l, int r, int x)
{
if (l == r) return void(Mn[p] = tag[p] = INF + 1);
pushdown(p);
int mid = l + r >> 1;
if (x <= mid) pushflag(ls, l, mid, x);
else pushflag(rs, mid + 1, r, x);
pushup(p);
}
void solve()
{
LL ans = 0, lst = 0;
for(re int i = 1; i <= n; i++)
if (!bz[i])
{
cnt = 0, ++color, dfs(i), sort(Q + 1, Q + cnt + 1);
int r = 1;
while (bz[b[r].x] == color && r <= n) ++r;
for(re int l = 1; l <= cnt; l++) id[Q[l]] = l;
for(re int l = 1; l <= cnt; l++)
{
build(1, 1, cnt), modify(1, 1, cnt, l, l, 0);
for(re int j = 1; j <= cnt; j++)
{
node now = node{Mp[1], Mn[1]};
for(re int k = h[Q[now.x]]; k; k = e[k].nxt) modify(1, 1, cnt, id[e[k].to], id[e[k].to], now.s + e[k].w);
if (d[Q[now.x]].size())
{
modify(1, 1, cnt, 1, id[d[Q[now.x]][0]] - 1, now.s + a[Q[now.x]]);
for(re int k = 1; k < d[Q[now.x]].size(); k++)
modify(1, 1, cnt, id[d[Q[now.x]][k - 1]] + 1, id[d[Q[now.x]][k]] - 1, now.s + a[Q[now.x]]);
modify(1, 1, cnt, id[d[Q[now.x]][d[Q[now.x]].size() - 1]] + 1, cnt, now.s + a[Q[now.x]]);
}
else modify(1, 1, cnt, 1, cnt, now.s + a[Q[now.x]]);
if (r <= n) modify(1, 1, cnt, 1, cnt, now.s + a[Q[now.x]] + b[r].s);
ans += (dis[now.x] = now.s), pushflag(1, 1, cnt, now.x);
}
LL mi = INF;
for(re int j = 1; j <= cnt; j++) mi = min(mi, dis[j] + a[Q[j]]);
ans += mi * (n - cnt);
}
}
printf("%lld\n", ans);
}
int main()
{
freopen("happybean.in", "r", stdin), freopen("happybean.out", "w", stdout);
read(n), read(m);
for(re int i = 1; i <= n; i++) read(a[i]), b[i].x = i, b[i].s = a[i]; sort(b + 1, b + n + 1, cmp);
for(re int i = 1, x, y, z; i <= m; i++)
read(x), read(y), read(z), add_edge(x, y, z), d[x].push_back(y), add_Edge(x, y), add_Edge(y, x);
for(re int i = 1; i <= n; i++) sort(d[i].begin(), d[i].end());
solve();
}
JZOJ 7377.欢乐豆的更多相关文章
- (jzoj snow的追寻)线段树维护树的直径
jzoj snow的追寻 DFS序上搞 合并暴力和,记录最长链和当前最远点,距离跑LCA # include <stdio.h> # include <stdlib.h> # ...
- [jzoj]3506.【NOIP2013模拟11.4A组】善良的精灵(fairy)(深度优先生成树)
Link https://jzoj.net/senior/#main/show/3506 Description 从前有一个善良的精灵. 一天,一个年轻人B找到她并请他预言他的未来.这个精灵透过他的水 ...
- [jzoj]3468.【NOIP2013模拟联考7】OSU!(osu)
Link https://jzoj.net/senior/#main/show/3468 Description osu 是一款群众喜闻乐见的休闲软件. 我们可以把osu的规则简化与改编成以下的样子: ...
- [jzoj]5478.【NOIP2017提高组正式赛】列队
Link https://jzoj.net/senior/#main/show/5478 Description Sylvia 是一个热爱学习的女孩子. 前段时间,Sylvia 参加了学校 ...
- [jzoj]1115.【HNOI2008】GT考试
Link https://jzoj.net/senior/#main/show/1115 Description 申准备报名参加GT考试,准考证号为n位数X1X2X3...Xn-1Xn(0<=X ...
- [jzoj]2538.【NOIP2009TG】Hankson 的趣味题
Link https://jzoj.net/senior/#main/show/2538 Description Hanks 博士是BT (Bio-Tech,生物技术) 领域的知名专家,他的儿子名叫H ...
- [jzoj]4216.【NOIP2015模拟9.12】平方和
Link https://jzoj.net/senior/#main/show/4216 Description 给出一个N个整数构成的序列,有M次操作,每次操作有一下三种: ①Insert Y X, ...
- [jzoj]2938.【NOIP2012模拟8.9】分割田地
Link https://jzoj.net/senior/#main/show/2938 Description 地主某君有一块由2×n个栅格组成的土地,有k个儿子,现在地主快要终老了,要把这些土地分 ...
- [jzoj]2505.【NOIP2011模拟7.29】藤原妹红
Link https://jzoj.net/senior/#main/show/2505 Description 在幻想乡,藤原妹红是拥有不老不死能力的人类.虽然不喜欢与人们交流,妹红仍然保护着误入迷 ...
- [jzoj]3875.【NOIP2014八校联考第4场第2试10.20】星球联盟(alliance)
Link https://jzoj.net/senior/#main/show/3875 Problem 在遥远的S星系中一共有N个星球,编号为1…N.其中的一些星球决定组成联盟,以方便相互间的交流. ...
随机推荐
- js-day04-作业
// -------------------------Day04homework 大练习------------------------ #### 练习题1: * 显示用户输入内容 * 要求: 1. ...
- 《HTTP权威指南》– 2.HTTP报文与URL资源
URL与资源: 大多数URL方案的URL语法都建立在这个由9部分构成的通用格式上. 方案: 访问服务器以获取资源要使用哪种协议 用户: 某些方案访问资源时需要的用户名 密码: 用户名后面可能包含的密码 ...
- js 定时器(setInterval)
js 定时器 分类 编程技术 js 定时器有以下两个方法: setInterval() :按照指定的周期(以毫秒计)来调用函数或计算表达式.方法会不停地调用函数,直到 clearInterval() ...
- GO语言基础 为什么我要学习Golang以及GO语言入门普及
作为网络安全初学者,会遇到采用Go语言开发的恶意样本.因此从今天开始从零讲解Golang编程语言,一方面是督促自己不断前行且学习新知识:另一方面是分享与读者,希望大家一起进步.这系列文章入门部分将参考 ...
- [攻防世界][江苏工匠杯]unseping
打开靶机对应的url 上来就是代码审计 <?php highlight_file(__FILE__); class ease{ private $method; private $args; f ...
- 90%的Java开发人员都会犯的5个错误
前言 作为一名java开发程序员,不知道大家有没有遇到过一些匪夷所思的bug.这些错误通常需要您几个小时才能解决.当你找到它们的时候,你可能会默默地骂自己是个傻瓜.是的,这些可笑的bug基本上都是你忽 ...
- [cocos2d-x]关于CC_CALLBACK
CC_CALLBACK的代码 // new callbacks based on C++11 #define CC_CALLBACK_0(__selector__,__target__, ...) s ...
- day01-Spring基本介绍
Spring基本介绍 1.官方资料和下载 1.1Spring5下载 直接访问 https://repo.spring.io/ui/native/release/org/springframework/ ...
- 【深入浅出Spring原理及实战】「源码调试分析」结合DataSourceRegister深入分析ImportBeanDefinitionRegistrar的源码运作流程
每日一句 人的一生中不可能会一帆风顺,总会遇到一些挫折,当你对生活失去了信心的时候,仔细的看一看.好好回想一下你所遇到的最美好的事情吧,那会让你感觉到生活的美好. 注入案例代码 如何通过实现Sprin ...
- Jest如何有序地执行测试
项目场景: node环境下编写js库,处于规范性考虑,需要做单元测试,我选择了Jest 问题描述 我的js库需要访问数据库,因此操作都是异步的,而且各个测试单元有严格的先后执行顺序(比如,建表 > ...