SRM733Hard
题意
\(n\) 个点竞赛图哈密尔顿回路。
\(1\ \leq\ n\ \leq\ 50\)
做法1
结论是 \(n\) 个点竞赛图有哈密尔顿回路当且仅当 \(SCC\) 个数是 \(1\)。
考虑每次增加一个点 \(i\),维护每个 \(SCC\) 哈密尔顿回路。
令 \(lst\) 为当前图 \(SCC\) 缩点后的链上最后一个有向连 \(i\) 边的点的 \(SCC\)。
令 \(fst\) 为当前图 \(SCC\) 缩点后的链上第一个有从 \(i\) 连边的点的 \(SCC\)。
若 \(lst\ <\ fst\) 则暴力插入。
若 \(lst\ =\ fst\) 则更新 \(lst\)。
若 \(lst\ >\ fst\) 则合并 \(fst\) 到 \(lst\) 中所有 \(SCC\)。
总复杂度 \(O(n^2)\)。
代码
#include<bits/stdc++.h>
using namespace std;
class HamiltonianCircuits {
public:
vector <int> findCircuit(int n, int seed, int a, int b, int c, vector <int> d, vector <int> e) {
vector<vector<int> > g(n, vector<int>(n, 0));
int value = seed;
for (int i = 0; i < n; ++i) {
for (int j = i + 1; j < n; ++j) {
if(value % 1000 <= 250) {
g[i][j] = 1;
g[j][i] = -1;
}
else {
g[i][j] = -1;
g[j][i] = 1;
}
value = ((long long) a * value + b) % c;
}
}
for (int i = 0; i < d.size(); ++i) g[d[i]][e[i]] = 1, g[e[i]][d[i]] = -1;
vector<vector<int> > ans; vector<int> bel(n);
for (int i = 0; i < n; ++i) {
for (int j = 0; j < ans.size(); ++j) for (int u: ans[j]) bel[u] = j;
int fst = n, lst = -1;
for (int j = 0; j < i; ++j) {
if(g[i][j] > 0) fst = min(fst, bel[j]);
if(g[i][j] < 0) lst = max(lst, bel[j]);
}
if(fst > lst) {
auto t = ans; ans.clear();
for (int j = 0; j <= lst; ++j) ans.push_back(t[j]);
ans.push_back(vector<int>{i});
for (int j = lst + 1; j < t.size(); ++j) ans.push_back(t[j]);
continue;
}
if(fst == lst) {
auto t = ans[fst];
for (int j = 0; j < t.size(); ++j) {
int u = t[j], v = t[(j + 1) % t.size()];
if(g[u][i] > 0 && g[i][v] > 0) {
ans[fst].clear();
for (int k = 0; k <= j; ++k) ans[fst].push_back(t[k]);
ans[fst].push_back(i);
for (int k = j + 1; k < t.size(); ++k) ans[fst].push_back(t[k]);
break;
}
}
continue;
}
auto t = ans; ans.clear();
for (int j = 0; j < fst; ++j) ans.push_back(t[j]);
ans.push_back(vector<int>{i});
for (int j = 0; j < t[fst].size(); ++j) if(g[i][t[fst][j]] > 0) {
ans.back().insert(ans.back().end(), t[fst].begin() + j, t[fst].end());
ans.back().insert(ans.back().end(), t[fst].begin(), t[fst].begin() + j);
break;
}
for (int j = fst + 1; j < lst; ++j) ans.back().insert(ans.back().end(), t[j].begin(), t[j].end());
for (int j = 0; j < t[lst].size(); ++j) if(g[i][t[lst][j]] < 0) {
ans.back().insert(ans.back().end(), t[lst].begin() + j + 1, t[lst].end());
ans.back().insert(ans.back().end(), t[lst].begin(), t[lst].begin() + j + 1);
break;
}
for (int j = lst + 1; j < t.size(); ++j) ans.push_back(t[j]);
}
return ans.size() == 1 ? ans[0] : vector<int>{};
}
};