T1:三色地图

本题难度中等,用 dfs 一边遍历每个点,一边枚举每个点的颜色。
直接枚举每个点的颜色是 O(3n) 会超时。所以在搜索时,要判断当前颜色是否和相邻点同色,如果同色要剪枝。原图不一定连通,所以要对每个连通块做染色搜索,将每个连通块的染色方案数相乘即为答案

代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
using ll = long long;
int n;
vector<vector<int>> to;
vector<int> used, col;
vector<int> vs;
void dfs(int v) {
if (used[v]) return;
used[v] = 1;
vs.push_back(v);
for (int u : to[v]) dfs(u);
}
ll now;
void dfs2(int i) {
if (i == vs.size()) { now++; return; }
int v = vs[i];
rep(c, 3) {
col[v] = c;
bool ok = true;
for (int u : to[v]) {
if (col[u] == c) ok = false;
}
if (!ok) continue;
dfs2(i + 1);
}
col[v] = -1;
}
int main() {
int m;
cin >> n >> m;
to = vector<vector<int>>(n);
rep(i, m) {
int a, b;
cin >> a >> b;
--a; --b;
to[a].push_back(b);
to[b].push_back(a);
}
ll ans = 1;
used = vector<int>(n);
col = vector<int>(n, -1);
rep(i, n) {
if (used[i]) continue;
ans *= 3;
vs = vector<int>();
dfs(i);
int s = vs.size();
col[vs[0]] = 0;
now = 0;
dfs2(1);
ans *= now;
}
cout << ans << '\n';
return 0;
}

T2: 最大值和最小值

本题难度较大,题目条件“最大数等于 x,最小数等于 y” 可以看作:子段内所有数满足 yax 且子段内含有至少一个 y 和至少一个 x

我们考虑用 dp[i][1/2/3] 记录 "以 ai 结尾的满足要求的子段个数",按照是否含有 xy 分类讨论
最后要注意 xy 有可能相同

  • xy,答案是 dp[i][3]
  • x=y,答案是 dp[i][1]