[ AGC006 F ] Blackout
题目
思路
代码
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int N = 100010, M = N << 1;
int n, m;
int h[N], val[M], ptr[M], w[M], idx;
int col[N], cnt[3], st[N];
void add(int a, int b, int c) { val[idx] = b, ptr[idx] = h[a], w[idx] = c, h[a] = idx++; }
int cal(int x) { return (x >= 3) ? x - 3 : ((x < 0) ? x + 3 : x); }
void DFS(int u, int &E, int &V, int &F) {
cnt[col[u]]++, st[u] = true, V++;
for (int i = h[u], v = val[i]; i != -1; i = ptr[i], v = val[i]) {
E += (w[i] == 1); // 是否为原边
if (!st[v]) col[v] = cal(col[u] + w[i]), DFS(v, E, V, F);
else if (col[v] != cal(col[u] + w[i])) F = 0;
}
}
int main() {
cin >> n >> m;
memset(h, -1, sizeof h);
for (int a, b; m-- && cin >> a >> b; )
add(a, b, 1), add(b, a, -1); // 加边权方便染色
long long res = 0;
for (int i = 1; i <= n; i++) {
if (st[i]) continue;
memset(cnt, 0, sizeof cnt);
int edge = 0, ver = 0, flag = 1;
DFS(i, edge, ver, flag);
if (!flag) res += 1ll * ver * ver;
else if (cnt[0] && cnt[1] && cnt[2])
res += 1ll * cnt[0] * cnt[1] +
1ll * cnt[1] * cnt[2] +
1ll * cnt[2] * cnt[0];
else res += edge;
}
cout << res << endl;
return 0;
}