K Tokitsukaze and Synthesis and Traits

实用的图论小技巧++
在这里插入图片描述
用题目给定的条件构造一张图
我们的目的就是在给定的点中找出原图中构成的边数

通过度数低的点向度数高的点建立有向边
可以保证每个点的出边 < 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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值