Gym 215177D 母亲节的礼物
Problem :
给n个点m条边的无向图,每个点的度数小于等于7,要求用4种不同的颜色给每个点染色,使得每个点相邻的点中最多只有一个相同颜色的点。(n<=25000)
Solution :
首先给每个点进行随机染色,调整不合法的点的颜色。对于某个不合法的点,必然可以找到一种颜色只出现过1次或0次,调整为这种颜色就行了。
考虑不合法的边的数量,假设一开始随机所有点的颜色都相同,那么一共有7n条不合法的边,而每次调整颜色必然可以减少至少一条不合法的边的数量。
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <string>
#include <map>
#include <vector>
#include <queue>
#include <ctime>
using namespace std;
#define f(i, x, y) for (int i = x; i <= y; ++i)
#define fd(i, x, y) for (int i = x; i >= y; --i)
#define rep(i, x, y) for (int i = x; i <= y; ++i)
#define repd(i, x, y) for (int i = x; i >= y; --i)
queue <int> Q;
const int INF = 1e9 + 7;
const int N = 200008;
int n, m, q;
vector <int> vec[N];
int dp[N];
int cnt[N], vis[N];
void init()
{
srand(time(NULL));
cin >> n >> m;
for (int i = 1; i <= n; ++i)
vec[i].clear();
for (int i = 1; i <= m; ++i)
{
int u, v;
cin >> u >> v;
vec[u].push_back(v);
vec[v].push_back(u);
}
}
void solve()
{
for (int i = 1; i <= n; ++i)
dp[i] = rand() % 4;
for (int i = 1; i <= n; ++i) Q.push(i), vis[i] = 1;
while (!Q.empty())
{
int u = Q.front(); Q.pop(); vis[u] = 0;
for (int i = 0; i < 4; ++i) cnt[i] = 0;
for (auto v : vec[u]) cnt[dp[v]]++;
if (cnt[dp[u]] <= 1) continue;
int qmin = INF, cl = 0;
for (int i = 0; i < 4; ++i)
if (cnt[i] < qmin)
{
qmin = cnt[i];
cl = i;
}
dp[u] = cl;
for (auto v : vec[u])
if (dp[v] == cl && !vis[v])
Q.push(v);
}
for (int i = 1; i <= n; ++i)
printf("%c",'a' + dp[i]);
printf("
");
}
int main()
{
cin.sync_with_stdio(0);
int T; cin >> T;
for (int cas = 1; cas <= T; ++cas)
{
init();
solve();
}
}