1130模拟赛 T1共同好友 乱搞解法
https://www.luogu.com.cn/problem/U124681
题目大意
给一个图
解法
对于所有询问,将度数较大的点作起点,度数较小的点作终点
以起点为第一关键字,终点为第二关键字将所有询问排序
按照排好的顺序遍历每个询问:
- 如果和上一个询问相同就直接记录答案
- 每当遍历到一个新的起点,标记新起点所能到达的所有点
- 暴力扫一遍终点能到达的所有点,每当找到标记的点就更新答案
然后就A了
复杂度证明
分别考虑起点和终点贡献的复杂度
起点
对于所有起点,每个点只在第一次出现时被扫到一次,所有边只被两边的点各扫到一次
起点贡献的复杂度只有
终点
将所有点的度数从达到小排序,记第
贡献时间复杂度
由于相同的询问被特判掉了,
显然,询问度数更大的点会使复杂度更高,前
总边数对终点的度数和作出限制
当
由于经过多次放缩,实际常数比较小
最终复杂度为
代码
# include <vector>
# include <cstdio>
# include <cstring>
# include <algorithm>
# define ll long long
using namespace std;
const int MAXN = 100051;
const int MAXM = 1000051;
struct Query{
int u, v, id;
bool operator == (const Query &o) const{
return u == o.u && v == o.v;
}
bool operator < (const Query &o) const{
if (u != o.u) return u < o.u;
else return v < o.v;
}
} q[MAXN];
struct Edge{
int u, v;
bool operator == (const Edge &o) const{
return u == o.u && v == o.v;
}
bool operator < (const Edge &o) const{
if (u != o.u) return u < o.u;
else return v < o.v;
}
} e[MAXM];
int n, m, t, gsz;
int ans[MAXN];
int vis[MAXN];
int dg[MAXN];
int fte[MAXN];
vector <int> g[MAXN];
int read(){
int nm = 0;
char x = getchar();
while (x < '0' || x > '9') x = getchar();
while (x >= '0' && x <= '9'){
nm = nm * 10 + x - '0';
x = getchar();
}
return nm;
}
int main(){
scanf("%d%d%d", &n, &m, &t);
for (int i = 1; i <= m; i++){
e[i].u = read();
e[i].v = read();
if (e[i].u > e[i].v) swap(e[i].u, e[i].v);
}
sort(e + 1, e + m + 1);
for (int i = 1; i <= m; i++){
if (e[i] == e[i - 1]) continue;
g[e[i].u].push_back(e[i].v);
g[e[i].v].push_back(e[i].u);
}
for (int i = 1; i <= t; i++){
q[i].u = read();
q[i].v = read();
q[i].id = i;
if (g[q[i].u].size() < g[q[i].v].size()) swap(q[i].u, q[i].v);
else if (g[q[i].u].size() == g[q[i].v].size() && q[i].u < q[i].v) swap(q[i].u, q[i].v);
}
sort(q + 1, q + t + 1);
for (int i = 1; i <= t; i++){
if (q[i] == q[i - 1]){
ans[q[i].id] = ans[q[i - 1].id];
continue;
}
if (q[i].u != q[i - 1].u){
for (int j = 0; j < g[q[i].u].size(); j++) vis[g[q[i].u][j]] = q[i].u;
}
if (q[i].u == q[i].v){
ans[q[i].id] = g[q[i].u].size();
continue;
}
int cnt = 0;
for (int j = 0; j < g[q[i].v].size(); j++){
cnt += (vis[g[q[i].v][j]] == q[i].u);
}
ans[q[i].id] = cnt;
}
for (int i = 1; i <= t; i++) printf("%d\n", ans[i]);
return 0;
}