码迷,mamicode.com
首页 > 其他好文 > 详细

hihoCoder #1161 八卦的小冰

时间:2017-12-26 14:30:42      阅读:158      评论:0      收藏:0      [点我收藏+]

标签:down   编程   $0   交换   body   集合   社交网络   logs   需要   

题目大意

考虑一个由 $n$ 个人构成的社交网络,其中任意两人都有一个用非负整数表示的亲密度。
初始时给出 $m$ 对人的亲密度,其余的亲密度为 $0$ 。
定义此社交网络的「八卦度」为异性之间的亲密度之和。
要求维护三种操作:

  1. 修改某人的性别
  2. 修改某两人的亲密度
  3. 询问八卦度

操作总数为 $q$ 。
数据范围:
$1 \le n, m, q \le 100000$

解法

这个社交网络可用一个无向图表示,亲密度为边的权值,按边所连接的两个点(人)的性别将边分为「同性边」和「异性边」。

先考虑暴力做法:
修改性别或亲密度都需要遍历某个点或某两个点的临接边表,复杂度太高。
一个优化是,用 std::map<pair<int,int>,int> 维护边的权值(即亲密度);
即便如此,修改性别仍需要遍历点的邻接边表。

正解是:
将无向图改造成有向图,边的方向由「度数小的点」指「向度数大的点」。
用 $c(u)$ 表示 $u$ 的出边的数目。

对每个点 $u$ 维护两个值 $s_1$, $s_2$,分别表示指向 $u$ 的边中同性边的权值之和 和 异性边的权值之和。

这样,对于改变点 $u$ 性别的操作,需要:

  1. 交换 $s_1[u]$ 和 $s_2[u]$ 。
  2. 对 $u$ 的出边指向的点 $v$,修改 $s_1[v]$ 和 $s_2[v]$ 。

复杂度为 $O(c(u))$

对于修改亲密度的操作,首先找到对应的那条边 $(u,v)$,修改其权值,再更新 $s_1[v]$ 和 $s_2[v]$ 。

复杂度为 $O(c(u) + c(v))$

下面证明 $c(u) = O(\sqrt{m}) $,$m$ 是边数。
证明:点 $u$ 的出边指向的点的总度数为 $\sum_{v\colon (u,v)\in E}$,

$2m > \sum_{v\colon (u,v)\in E} d(v) \ge c(u) d(u) \ge c(u)^2 $

$c(u) < \sqrt{2m}$
所以 $c(u) = O(\sqrt{m})$ 。

上述证明里所考虑的图是静态的。对于这个题目,我们可以采用离线的方式,将动态图转化成静态图,但这样就增加了编程复杂度。
下面考虑在动态添边的情况下是否还有类似的结论。

为了便于描述,我们把 $u$ 的出边所指向的点称作 $u$ 的「出邻点」,将 $u$ 的出邻点的集合记作 $N^-(u)$,则 $c(u) = |N^-(u)|$ 。
令 $d(N^-(u)) = \sum_{v\in N^-(u)} d(v)$ 。

考虑往途中增加一条(有向)边 $(u,v)$ 之后的情形:
$d(u) \to d(u)+1$
$d(N^-(u))$ 的增量 $\Delta$ 满足
$\Delta \ge d(u) + 1 $

所以
$2m > d(N^-(u)) \ge 1 + 2 + 3 + \dots + c(u)$
同样有
$c(u) = O(\sqrt{m})$

hihoCoder #1161 八卦的小冰

标签:down   编程   $0   交换   body   集合   社交网络   logs   需要   

原文地址:https://www.cnblogs.com/Patt/p/8116528.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!