DAGの最小パス被覆。Dilworthの定理。
サイクルに含まれるような頂点は無視する。
const int N = 100 + 5; vector<int> g[N]; bool h[N][N]; int match[N]; bool vis[N]; void add_edge(int src, int dst) { dst += 50; g[src].push_back(dst); g[dst].push_back(src); return ; } bool rec(int v) { vis[v] = true; for (int i = 0; i < g[v].size(); ++i) { int u = g[v][i]; int w = match[u]; if (w < 0 || !vis[w] && rec(w)) { match[v] = u; match[u] = v; return true; } } return false; } int matching(void) { fill(match, match + N, -1); int ret = 0; for (int i = 0; i < N; ++i) { if (match[i] == -1) { fill(vis, vis + N, false); if (rec(i)) ++ret; } } return ret; } class Incubator { public: int maxMagicalGirls(vector <string> love) { const int M = love.size(); for (int i = 0; i < M; ++i) { for (int j = 0; j < M; ++j) { h[i][j] = (love[i][j] == 'Y'); } } for (int k = 0; k < N; ++k) { for (int i = 0; i < N; ++i) { for (int j = 0; j < N; ++j) { h[i][j] = h[i][j] || (h[i][k] && h[k][j]); } } } int cyc = 0; for (int i = 0; i < N; ++i) { cyc += h[i][i]; } fill(g, g + N, vector<int>()); for (int i = 0; i < M; ++i) { for (int j = 0; j < M; ++j) { if (h[i][j] && !h[i][i] && !h[j][j]) { add_edge(i, j); } } } return max(0, M - matching() - cyc); };