codeforces ASC28J 三元环计数

版权声明:_ https://blog.csdn.net/lunch__/article/details/82224428

题面

这个题也不是很难,就是个一般的三元环计数

今天用一种奇怪的做法 b i t s e t 来优化

b i t s e t 是个很好用的东西 类似于一个二进制数 但是时间和空间消耗都很小

它大概有以下操作

1. 所有的位运算,例如 << , >> , | , 还有&运算

2. 一些相关的函数

#include<iostream>
#include<bitset>

std::bitset<233> f;

int main() {
    f.size(); //bitset的大小 在这里就是233
    f.count(); //bitset 中二进制1的个数
    f.set(); //所有位都设为1
    f.reset(); //所有的位都设为0
    f.set(u); //把第u位设为1
    f.reset(u); //把第u位设为0
    f.any(); //是否存在一位是1
    f[x]; // 访问第x位的元素
    f.flip(); //取反所有位
    f.flip(x); //取反第x位
    f.to_ulong(); //转化为unsigned long 并返回
}

反正这个东西自带一个 1 ω 的常数,可以优化一些过不了的东西

64 位的机器上 ω = 64 这样子 n 3 的算法就可以优化到 O ( n 3 ω ) 就能跑 n = 1000

这个题加上 b i t s e t 的做法之后就可以直接跑最暴力的做法了

首先把每个点的出边和入边都用 b i t s e t 存下来

然后暴力枚举两个点, a > b , 把 a 的入边和 b 的出边进行与操作后里面 1 的个数加入答案就够了。

因为三元环每条边都被枚举到了一次 最后答案除个3就好了

记得开 l o n g l o n g

复杂度 O ( n 3 ω )

Codes

#include<bits/stdc++.h>

using namespace std;

const int N = 1500 + 10;
bitset<N> in[N], out[N];
int a[N][N], ans;

int main() {
    freopen("triatrip.in", "r", stdin);
    freopen("triatrip.out", "w", stdout);
    int n; long long ans = 0; char c;
    scanf("%d", &n);
    for(int i = 1; i <= n; ++ i) 
        for(int j = 1; j <= n; ++ j) {
            cin >> c;
            if(c == '+') {
                a[i][j] = 1; 
                out[i][j] = 1;
                in[j][i] = 1;
            }
        }
    for(int i = 1; i <= n; ++ i)
        for(int j = 1; j <= n; ++ j)
            if(a[i][j])
                ans += (out[j] & in[i]).count();
    cout << ans / 3 << endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/lunch__/article/details/82224428