zoukankan      html  css  js  c++  java
  • BZOJ 2208: [Jsoi2010]连通数 Tarjan

    2208: [Jsoi2010]连通数

    Description

    Input

    输入数据第一行是图顶点的数量,一个正整数N。 接下来N行,每行N个字符。第i行第j列的1表示顶点i到j有边,0则表示无边。

    Output

    输出一行一个整数,表示该图的连通数。

    Sample Input

    3
    010
    001
    100

    Sample Output

    9

    思路 :

      tarjan  + 拓扑排序 + dp + STL:: bitset 优化 f[i][j]表示从i到j这种状态的答案, 把jbitset压一个32就可以过了

    代码:

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <stack>
    #include <bitset>
    #include <queue>
    using namespace std;
    const int N = 2100, M = 4001000;
    int head[N], to[M], nxt[M], cnt;
    int dfn[N], low[N], place[N], val[N], idx, tot;
    int map[N][N];
    bool vis[N][N];
    int ind[N];
    stack<int>s;
    bitset<N> f[N];
    int ins[N];
    void add(int x, int y) {
        to[++cnt] = y;
        nxt[cnt] = head[x];
        head[x] = cnt;
    }
    void Tarjan(int p) {
        dfn[p] = low[p] = ++idx;
        ins[p] = 1;s.push(p);
        for(int i=head[p];i;i=nxt[i]) {
            if(!dfn[to[i]]) {
                Tarjan(to[i]);
                low[p] = min(low[p], low[to[i]]);
            }
            else if(ins[to[i]]) {
                low[p] = min(low[p], dfn[to[i]]);
            }
        }
        if(dfn[p]==low[p]) {
            int t = 0;
            tot++;
            while(t!=p) {
                t = s.top();s.pop();
                ins[t] = 0;
                place[t] = tot;
                val[tot]++;
            }
        }
    }
    int n;
    void rebuild() {
        memset(head, 0, sizeof(head));
        cnt = 0;
        for(int i=1;i<=n;i++) {
            for(int j=1;j<=n;j++) {
                if(map[i][j]&&place[i]!=place[j])
                    ind[place[i]]++,add(place[j], place[i]);
            }
        }
        for(int i=1;i<=tot;i++) f[i][i]=1;
    }
    int ans = 0;
    void topo() {
        queue<int>q;
        for(int i=1;i<=tot;i++) if(!ind[i]) q.push(i);
        while(!q.empty()) {
            int u = q.front();q.pop();
            for(int i=head[u];i;i=nxt[i]) {
                ind[to[i]]--;
                f[to[i]]|=f[u];
                if(!ind[to[i]])q.push(to[i]);
            }
        }
        for(int i=1;i<=tot;i++) {
            for(int j=1;j<=tot;j++) {
                if(f[i][j]) ans += val[i] * val[j];
            }
        }
    }
    int main() {
        scanf("%d", &n);
        for(int i=1;i<=n;i++) {
            for(int j=1;j<=n;j++) {
                scanf("%1d", &map[i][j]);
                if(map[i][j]) add(i, j);
            }
        }
        for(int i=1;i<=n;i++) {
            if(!dfn[i]) Tarjan(i);
        }
        rebuild();
        topo();
        printf("%d
    ", ans);
    }
  • 相关阅读:
    献给 Python 开发人员的 25 个最佳 GitHub 代码库!
    6 drf-认证权限解析频率
    4: drf视图组件
    3 drf请求与响应
    十三:Django框架学习之auth模块
    十二:django中间件学习之拓展1
    git光速从入门到精通
    mac系统下的mysql安装(ver.8.0.20)
    python小练习——2048
    docker下overlay2占用空间过大,清理docker占用空间
  • 原文地址:https://www.cnblogs.com/Tobichi/p/9230750.html
Copyright © 2011-2022 走看看