图染色
作者:互联网
图染色
根号分治
图染色 - 题目 - Daimayuan Online Judge
图染色问题一般可用,树染色可用 dp 等方法
- 设一个阈值 M
- 度数大于 M 的点可设为大点,<= M 的设为小点
查询
- 若为小点,直接暴力枚举邻居,最多枚举 M 个
- 若为大点,不能暴力枚举,可考虑在修改的时候就算出来大点的答案
修改
可预处理出每个点的大点邻居,存到 B 数组里,当反转这个点时,直接更新它的大点邻居,复杂度为 \(O(\frac {边数}M)\)
不能也更新小点,因为小点邻居可能很多
设 M 为 \(\sqrt {边数}\) 即可
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <cmath>
using namespace std;
#define endl "\n"
typedef long long ll;
typedef pair<int, int> PII;
const int N = 2e5 + 10, M = 500;
int n, m, q;
vector<vector<int> > G(N), B(N);
bool big[N];
int col[N], ans[N];
void add(int u, int v)
{
G[u].push_back(v);
}
int main()
{
scanf("%d%d%d", &n, &m, &q);
while(m--)
{
int u, v;
scanf("%d%d", &u, &v);
add(u, v), add(v, u);
}
for (int i = 1; i <= n; i++)
if (G[i].size() > M) big[i] = true;
for (int u = 1; u <= n; u++)
{
for (auto v : G[u])
{
if (big[v])
B[u].push_back(v);
}
}
while(q--)
{
int op, x;
scanf("%d%d", &op, &x);
if (op == 1)
{
col[x] ^= 1;
for (int y : B[x])
{
if (col[x])
ans[y]++;
else
ans[y]--;
}
}
else
{
if (big[x])
printf("%d\n", ans[x]);
else
{
int cnt = 0;
for (int y : G[x])
cnt += col[y];
printf("%d\n", cnt);
}
}
}
return 0;
}
标签:int,染色,d%,大点,add,include 来源: https://www.cnblogs.com/hzy717zsy/p/16365581.html