ABC 158 D(图,fake)
前言
(截图于kenkoooo.com)
嗯,没错,这是一道青题。所以这是一道E题
不过照样被我自己做出来了。
做出这题算什么,我可是全世界最弱的
链接:$ \sum _ {i = 1} ^ {n} {a}_{i} $
正文
题目大意
Takahashi 有一个 SNS。(下文我们称为WorldBBS)
在 WorldBBS 上,有朋友,也有死对头。
现在,我们的 Takahashi 要增加一个新功能:朋友推荐。
如果 y 要被推荐给 x,则必须满足以下几个要求:
- y 不是 x 的朋友。(不然还推荐干啥)
- y 不是 x 的死对头。(推荐了也不会加)
- y 是 x 的间接朋友。所谓的间接朋友是指 y 是 x 的朋友的朋友的朋友……这里不论是有 2 个“朋友”还是 1000000 个都没关系。
现在让你求出被推荐给每个人的朋友数。
思路
这题一看就是个图,毕竟我们可以按照友谊和死对头关系建两张图嘛!
对于友谊我们处理出每个连通集,并处理出每个连通集的节点个数。
首先我们把节点个数减 1 后再减朋友的个数,因为朋友推荐总不能推荐原先的朋友(离谱)和自己(更离谱)嘛。
对于那些间接的死对头咋办呢?(比如:1 3 是朋友,3 2 是朋友,1 2 是死对头)
考虑到每个人的死对头加起来才 $ 100000 \times 2 = 200000 $。
我们可以把连通集存进 set 而非 vector 里,然后找到一个就减 1。
Over.
代码
#include <bits/stdc++.h>
using namespace std;
vector<set<int> > comp;
int len;
vector<int> good[100005], bad[100005];
int vis[100005];
void dfs(int x, int flag) {
if (vis[x]) {
return;
}
vis[x] = flag;
comp[flag].insert(x);
for (auto adjacent : good[x]) {
dfs(adjacent, flag);
}
}
int main() {
int n, m, k;
scanf("%d %d %d", &n, &m, &k);
for (int i = 0; i < m; i++) {
int a, b;
scanf("%d %d", &a, &b);
a--, b--;
good[a].push_back(b);
good[b].push_back(a);
}
for (int i = 0; i < k; i++) {
int c, d;
scanf("%d %d", &c, &d);
c--;
d--;
bad[c].push_back(d);
bad[d].push_back(c);
}
comp.emplace_back();
for (int i = 0; i < n; i++) {
if (!vis[i]) {
comp.emplace_back();
dfs(i, ++len);
}
}
for (int i = 0; i < n; i++) {
int ans = comp[vis[i]].size() - good[i].size();
for (int blocked : bad[i]) {
ans -= comp[vis[i]].count(blocked);
}
printf("%d ", ans - 1);
}
return 0;
}
后续
kenkoooo是个好网站!
它不仅能统计你的AC数,连续AC天数,当然还有那个古怪的TEE(tourist 把你 AC 过的题全刷一遍要多少秒)外,还能统计题目的Rating并给你推荐题目!
比方说这题,我就是在Hard的题目中找到这题的。
但是kenkoooo好像也就这个东东了……
各位神犇们行行好吧
蒟蒻推荐太少了
求大家推荐一下吧
大家都是OIer这个物种啊!!!