[ AGC006 F ] Blackout

题目

Atcoder

思路

006F01.png
006F02.png

代码

#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;
}
posted @ 2021-05-29 12:37  Protein_lzl  阅读(29)  评论(0编辑  收藏  举报