Serie: Algorithms
cpp
149 líneas
· Actualizado 2026-07-24
graph_coloring.cpp
Algorithms/Advanced/graph_coloring.cpp
// graph_coloring.cpp
// -----------------------------------------------------------------
// Graph Coloring(圖著色):
// 1. 回溯 + 剪枝:判斷 k 色可行並輸出著色
// 2. 色數(chromatic number):從 k=1 遞增測試
// 3. 貪婪著色(Welsh-Powell:度數大者優先)——快速上界
//
// Compile: g++ -std=c++17 -O2 -Wall -Wextra -o graph_coloring graph_coloring.cpp
// -----------------------------------------------------------------
#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
using namespace std;
// ---------- 1. 回溯 k-著色 ----------
class ColoringBacktrack {
const vector<vector<int>>& adj;
int n, k;
vector<int> color;
public:
long long nodes = 0;
ColoringBacktrack(const vector<vector<int>>& g)
: adj(g), n((int)g.size()) {}
// 回傳 {可行?, 著色方案}
pair<bool, vector<int>> solve(int k_) {
k = k_;
color.assign(n, -1);
nodes = 0;
bool ok = dfs(0);
return {ok, color};
}
private:
bool feasible(int u, int c) {
for (int v : adj[u])
if (color[v] == c) return false;
return true;
}
bool dfs(int u) {
++nodes;
if (u == n) return true;
for (int c = 0; c < k; ++c) {
if (!feasible(u, c)) continue; // 剪枝
color[u] = c;
if (dfs(u + 1)) return true;
color[u] = -1;
}
return false;
}
};
// ---------- 2. 色數:遞增 k ----------
int chromaticNumber(const vector<vector<int>>& g) {
ColoringBacktrack cb(g);
for (int k = 1; k <= (int)g.size(); ++k)
if (cb.solve(k).first) return k;
return (int)g.size();
}
// ---------- 3. 貪婪著色(Welsh-Powell 順序) ----------
pair<int, vector<int>> greedyColoring(const vector<vector<int>>& g) {
int n = (int)g.size();
vector<int> order(n);
iota(order.begin(), order.end(), 0);
sort(order.begin(), order.end(), [&](int a, int b) {
return g[a].size() > g[b].size(); // 度數遞減
});
vector<int> color(n, -1);
int used = 0;
for (int u : order) {
vector<bool> ban(n, false);
for (int v : g[u])
if (color[v] != -1) ban[color[v]] = true;
int c = 0;
while (ban[c]) ++c;
color[u] = c;
used = max(used, c + 1);
}
return {used, color};
}
static vector<vector<int>> buildGraph(int n, const vector<pair<int,int>>& edges) {
vector<vector<int>> g(n);
for (auto [u, v] : edges) {
g[u].push_back(v);
g[v].push_back(u);
}
return g;
}
static void report(const string& name, const vector<vector<int>>& g) {
ColoringBacktrack cb(g);
int chi = chromaticNumber(g);
auto [greedyK, gc] = greedyColoring(g);
auto [ok, col] = cb.solve(chi);
cout << name << ": chromatic number = " << chi
<< " | greedy used = " << greedyK
<< (greedyK > chi ? " (greedy overshoots!)" : "") << "\n";
if (ok) {
cout << " optimal coloring:";
for (int i = 0; i < (int)col.size(); ++i)
cout << " v" << i << "=c" << col[i];
cout << "\n";
}
(void)gc;
}
int main() {
// ---- 範例 1:三角形 K3(色數 3) ----
cout << "=== Example 1: triangle K3 ===\n";
report("K3", buildGraph(3, {{0,1},{1,2},{2,0}}));
cout << "\n";
// ---- 範例 2:偶環 C4 vs 奇環 C5 ----
cout << "=== Example 2: even cycle C4 (bipartite) vs odd cycle C5 ===\n";
report("C4", buildGraph(4, {{0,1},{1,2},{2,3},{3,0}}));
report("C5", buildGraph(5, {{0,1},{1,2},{2,3},{3,4},{4,0}}));
cout << "\n";
// ---- 範例 3:Petersen 圖(著名例子,色數 3) ----
cout << "=== Example 3: Petersen graph ===\n";
vector<pair<int,int>> pet = {
{0,1},{1,2},{2,3},{3,4},{4,0}, // 外圈
{5,7},{7,9},{9,6},{6,8},{8,5}, // 內五角星
{0,5},{1,6},{2,7},{3,8},{4,9} // 輻條
};
report("Petersen", buildGraph(10, pet));
cout << "\n";
// ---- 範例 4:排課情境(衝突圖著色 = 時段分配) ----
cout << "=== Example 4: exam scheduling as coloring ===\n";
// 6 門課,邊 = 有共同學生(不能同時段)
// 課程: 0=微積分 1=線代 2=物理 3=化學 4=程設 5=英文
vector<pair<int,int>> conflicts = {
{0,1},{0,2},{1,2},{1,3},{2,4},{3,4},{3,5},{4,5}
};
auto g = buildGraph(6, conflicts);
int chi = chromaticNumber(g);
ColoringBacktrack cb(g);
auto [ok, col] = cb.solve(chi);
const char* names[] = {"Calculus","LinAlg","Physics","Chem","Prog","English"};
cout << "6 courses, 8 conflicts -> minimum time slots = " << chi << "\n";
if (ok)
for (int i = 0; i < 6; ++i)
cout << " slot " << col[i] << ": " << names[i] << "\n";
return 0;
}
Artículos relacionados
Algorithms
java
Actualizado 2026-03-02
#include <iostream>.java
#include <iostream>.java — java source code from the Algorithms learning materials (Algorithms/#include <iostream>.java).
Leer artículo →
Algorithms
cpp
Actualizado 2026-04-07
748.cpp
748.cpp — cpp source code from the Algorithms learning materials (Algorithms/748.cpp).
Leer artículo →
Algorithms
cpp
Actualizado 2026-04-07
827.cpp
827.cpp — cpp source code from the Algorithms learning materials (Algorithms/827.cpp).
Leer artículo →
Algorithms
cpp
Actualizado 2026-04-07
827_best_greedy.cpp
827_best_greedy.cpp — cpp source code from the Algorithms learning materials (Algorithms/827_best_greedy.cpp).
Leer artículo →
Algorithms
cpp
Actualizado 2026-04-07
8402.cpp
8402.cpp — cpp source code from the Algorithms learning materials (Algorithms/8402.cpp).
Leer artículo →
Algorithms
cpp
Actualizado 2026-04-07
860.cpp
860.cpp — cpp source code from the Algorithms learning materials (Algorithms/860.cpp).
Leer artículo →