2022.10.14 总结
1. 逐月 P8006
题意#
小
小
现在小
思路#
100 分#
我们可以将珍珠视为点,问题视为边,所以,这个题目就变成了一道模板的 二分图染色 了。
先介绍一下二分图:
对于每一个点,都可以染成黑色或者白色,存在一种方案,使得任意相邻两个点的颜色都不同。
所以,这就是一个图的深搜(耶!)
那么,什么时候这个图是不合法的呢?
就是,当这个点已经被遍历过了,并且,它的颜色和它应该是的颜色不同,就说明,这个图是不合法的。
但是,要怎么求方案数呢?
先说结论,令
因为,对于每个连通块,可以把它们分成两个部分,第一个部分的点颜色为
所以方案数是
然后,事情就变得简单了,直接做图的遍历即可。
时间复杂度#
图的遍历,点数 + 边数,
空间复杂度#
邻接表,
代码#
#include <bits/stdc++.h>
using namespace std;
const int N = 300010, MOD = 998244353;
int n, m, tp, x, y, w, cnt, v[N];
bool flag = 1;
struct C{
int d, w;
};
vector<C> f[N];
void dfs(int t, int co){ // 二分图染色
if (v[t] != -1) {
flag &= (v[t] == co);
return ;
}
v[t] = co;
for (int i = 0; i < f[t].size(); i++) {
dfs(f[t][i].d, f[t][i].w ^ co);
}
}
int main(){
freopen("pearl.in", "r", stdin);
freopen("pearl.out", "w", stdout);
cin >> n >> m >> tp;
fill(v + 1, v + n + 1, -1);
for (int i = 1; i <= m; i++) {
cin >> x >> y >> w;
f[x].push_back({y, !w}), f[y].push_back({x, !w}); // 邻接表
}
for (int i = 1; i <= n; i++) {
if (v[i] == -1) {
cnt++;
dfs(i, 0); // 搜索连通块
}
}
if (!flag) {
if (tp == 1) {
cout << "NO";
} else {
cout << 0;
}
} else {
if (tp == 1) {
cout << "YES";
} else {
long long ans = 1;
for (int i = 1; i <= cnt; i++) {
ans = ans * 2 % MOD;
}
cout << ans;
}
}
return 0;
}
作者:cn
出处:https://www.cnblogs.com/chengning0909/p/17173890.html
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】