Educational Codeforces Round 56 (Rated for Div. 2) 1093

D. Beautiful Graph

思路

  • 拿到这个题目,我们发现,只有 1 , 3 1,3 1,3 奇数和 2 2 2 偶数搭配才能 b e a u t i f u l beautiful beautiful ,对于 1 , 3 1,3 1,3 填哪一个都可以,所以我们可以把问题转化为什么时候填 1 1 1 什么时候填 0 0 0
  • 我们需要注意的就是,这不一定会形成一个 g r a p h graph graph 可能是多个不连通的 g r a p h graph graph

细节注释

  • 注释1:当这个点被 d f s dfs dfs 搜过就不用搜了,这是为了防止出现多个不联通的 g r a p h graph graph
  • 注释2: o k ok ok 的意思是,能不能形成一个连通且 b e a u t i f u l beautiful beautiful 的图, e v e n even even
    的意思是,共有几个点可以填写 0 0 0 o d d odd odd 的意思是,共有几个点可以填写 1 1 1
  • 注释3,5:搜每个没搜过的点,都标记为 0 0 0,至于为什么只标记为 0 0 0 不考虑标记 1 1 1,因为标记为 0 0 0 e v e n even even 就是标记为 1 1 1 时的 o d d odd odd 2 o d d 2^{odd} 2odd + 2 e v e n 2^{even} 2even,考虑的就是 1 , 3 1,3 13 的填写
  • 注释4:不能形成一个 b e a u t i f u l beautiful beautiful 的图
  • 注释6:搜过了,或者是不 b e a u t i f u l beautiful beautiful 立刻结束这个点的所有 d f s dfs dfs
  • 注释7,8:这个点是啥,并标注这个点是啥(这个点没被搜过)
  • 注释9:这个图不 b e a u t i f u l beautiful beautiful
  • 注释10:接着搜完这个 g r a p h graph graph,统计 e v e n even even o d d odd odd

总结

  • m e m s e t memset memset 可能超时
  • f o r for for 循环中的 e d g e [ u ] . s i z e ( ) edge[u].size() edge[u].size() 也会延长时间,用 l e n len len 替代
AC(dfs and similar + graphs)
#include <bits/stdc++.h>
using namespace std;
#define PB push_back
typedef long long LL;
typedef vector<int> VI;
const int mod = 998244353;
const int N = 3e5 + 10;
VI edge[N];
int num[N];
int n, m;
bool ok;
LL even, odd;
LL qmi(int cnt) {
	LL ans = 1;
	LL a = 2;
	for (; cnt; cnt >>= 1) {
		if (cnt & 1) ans = ans * a % mod;
		a = a * a % mod;
	}
	return ans;
}
void dfs(int u, int v) {
	if (!ok || num[u] != -1) return; //注释6
	if (v % 2) odd ++; //注释7
	else even ++;
	num[u] = v; //注释8
	int len = edge[u].size();
	for (int i = 0; i < len; i ++ ) {
		int tmp = edge[u][i];
		if (num[tmp] == v) { //注释9
			ok = 0;
			return;
		} 
		dfs(tmp, (v + 1) % 2); //注释10
	}
}
int main() {
	int t;
	scanf("%d", &t);
	while (t -- ) {
		scanf("%d%d", &n, &m);
		for (int i = 1; i <= n; i ++ ) {
			edge[i].clear();
			num[i] = -1;
		}
		for (int i = 1; i <= m; i ++ ) {
			int u, v;
			scanf("%d%d", &u, &v);
			edge[u].PB(v);
			edge[v].PB(u);
		}
		LL ans = 1;
		for (int i = 1; i <= n; i ++ ) {
			if (num[i] != -1) continue; //注释1
			ok = 1, even = 0, odd = 0; //注释2
			dfs(i, 0); //注释3
			if (!ok) { //注释4
				ans = 0;
				break;
			} else {
				LL tmp = (qmi(even) + qmi(odd)) % mod; // 注释5
				ans = ans * tmp % mod;
			}
		}
		printf("%lld\n", ans);
	}
	return 0; 
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值