forked from kth-competitive-programming/kactl
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathEdgeColoring.h
46 lines (45 loc) · 1.54 KB
/
EdgeColoring.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
/**
* Author: Simon Lindholm
* Date: 2020-10-12
* License: CC0
* Source: https://en.wikipedia.org/wiki/Misra_%26_Gries_edge_coloring_algorithm
* https://codeforces.com/blog/entry/75431 for the note about bipartite graphs.
* Description: Given a simple, undirected graph with max degree $D$, computes a
* $(D + 1)$-coloring of the edges such that no neighboring edges share a color.
* ($D$-coloring is NP-hard, but can be done for bipartite graphs by repeated matchings of
* max-degree nodes.)
* Time: O(NM)
* Status: stress-tested, tested on kattis:gamescheduling
*/
#pragma once
vi edgeColoring(int N, vector<pii> eds) {
vi cc(N + 1), ret(sz(eds)), fan(N), free(N), loc;
for (pii e : eds) ++cc[e.first], ++cc[e.second];
int u, v, ncols = *max_element(all(cc)) + 1;
vector<vi> adj(N, vi(ncols, -1));
for (pii e : eds) {
tie(u, v) = e;
fan[0] = v;
loc.assign(ncols, 0);
int at = u, end = u, d, c = free[u], ind = 0, i = 0;
while (d = free[v], !loc[d] && (v = adj[u][d]) != -1)
loc[d] = ++ind, cc[ind] = d, fan[ind] = v;
cc[loc[d]] = c;
for (int cd = d; at != -1; cd ^= c ^ d, at = adj[at][cd])
swap(adj[at][cd], adj[end = at][cd ^ c ^ d]);
while (adj[fan[i]][d] != -1) {
int left = fan[i], right = fan[++i], e = cc[i];
adj[u][e] = left;
adj[left][e] = u;
adj[right][e] = -1;
free[right] = e;
}
adj[u][d] = fan[i];
adj[fan[i]][d] = u;
for (int y : {fan[0], u, end})
for (int& z = free[y] = 0; adj[y][z] != -1; z++);
}
rep(i,0,sz(eds))
for (tie(u, v) = eds[i]; adj[u][ret[i]] != v;) ++ret[i];
return ret;
}