3337. 我认识你
Time limit per test: 2.0 seconds
Memory limit: 256 megabytes
人与人之间的关系错综复杂,常常会出现一个叫作共同好友的东西。所以,贴心的 QQ 就提供了这样一个功能,可以显示你与某人(不一定是好友)有多少个共同好友。但是,当用户量逐渐增大,好友关系网不断复杂化,共同好友计算的效率就变得十分重要了。
你刚刚和腾讯公司签约,获得了共同好友计算的开发资格。
Input
第一行有两个整数 n,m (1≤n≤40 000,1≤m≤40 000)。分别表示用户数量和好友关系数量。方便起见,用户编号为 1 到 n。
接下来 m 行,每行两个整数用空格隔开 u,v (1≤u,v≤n,u≠v),表示 u 和 v 是好友。数据保证不会出现两对相同的 u,v。
接下来一行一个整数 q (1≤q≤40 000) 表示查询数。
接下来 q 行,每行两个整数 s,t (1≤s,t≤n,s≠t),表示询问的对象。
小数据规模说明:
- 对于前 20% 的数据有 1≤n≤10,1≤q≤200。
- 对于前 40% 的数据有 1≤n≤1 000。
Output
对于每组询问,输出这两个人有多少个共同好友。
Examples
input
3 3 1 2 1 3 3 2 2 1 3 3 2
output
1 1
input
4 4 1 2 1 4 2 3 3 4 3 1 3 1 4 2 4
output
2 0 2
input
3 2 1 2 1 3 2 2 3 2 3
output
1 1
题解:一开始用暴力做,邻接矩阵存每个点及与它相连的点
对于每个询问,用一个used数组标记有哪几个点同时与s和t相连,计数输出即可。
但这样O(qn)时间复杂度太高只能过50%数据。
考虑用bitset压位计算。
对每个人开一个bitset,如果与第i个人有关系则对应位置1,对于每个query,两者相与取1的个数即为答案。
代码看起来非常elegant。
#include <bits/stdc++.h>
#define vi vector<int>
using namespace std;
const int MAX_N = 4e4 + 10;
int used[MAX_N];
bitset<MAX_N> graph[MAX_N];
int seq[MAX_N];
int main()
{
// freopen("out.txt","w",stdout);
ios::sync_with_stdio(false);
cin.tie(0);
int n,m;
cin >> n >> m;
for(int i = 0; i < m; i++)
{
int u,v;
cin >> u >> v;
graph[u][v] = 1;
graph[v][u] = 1;
}
int q;
cin >> q;
while(q--)
{
int s,t;
cin >> s >> t;
bitset<MAX_N> temp = bitset<MAX_N>(graph[s] & graph[t]);
cout << temp.count()<<endl;
}
return 0;
}