实用的图论小技巧++
用题目给定的条件构造一张图
我们的目的就是在给定的点中找出原图中构成的边数
通过度数低的点向度数高的点建立有向边
可以保证每个点的出边
<
m
(
m
为总边数
)
<\sqrt{m}(m为总边数)
<m(m为总边数)
这样可以降低复杂度
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 3e5 + 10;
int n, m, q, du[N], U[N], V[N], cnt[N], a[N];
struct node {
int nxt, to;
}edge[N << 1];
int head[N], tot;
inline int read() {
int s = 0, w = 1;
char ch = getchar();
while(ch < '0' || ch > '9') {
if(ch == '-') w = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9') {
s = s * 10 + ch - '0';
ch = getchar();
}
return s * w;
}
inline void add_edge(int x, int y) {
edge[++tot].to = y;
edge[tot].nxt = head[x];
head[x] = tot;
}
int main () {
// scanf("%d %d %d", &n, &m, &q);
n = read(), m = read(), q = read();
for(int i = 1; i <= m; i ++ ) {
U[i] = read(), V[i] = read();
// scanf("%d %d", &U[i], &V[i]);
du[U[i]] ++ , du[V[i]] ++ ;
}
for(int i = 1; i <= m; i ++ ) {
if(du[U[i]] >= du[V[i]]) add_edge(V[i], U[i]);
else add_edge(U[i], V[i]);
}
while(q -- ) {
// for(int i = 1; i <= n; i ++ ) cnt[i] = 0;
// int k; scanf("%d", &k);
int k = read();
for(int i = 1; i <= k; i ++ ) {
// scanf("%d", &a[i]);
a[i] = read();
cnt[a[i]] = 0;
}
for(int p = 1; p <= k; p ++ ) {
for(int i = head[a[p]]; i; i = edge[i].nxt) {
int v = edge[i].to;
cnt[v] ++ ;
}
}
int ans = 0;
for(int i = 1; i <= k; i ++ ) ans += cnt[a[i]];
printf("%d\n", ans);
}
return 0;
}