zoukankan      html  css  js  c++  java
  • BZOJ从入门到入土

    1. [Jsoi2010]连通数:有向图求每一个点到能到达的点的个数的和(包括自己到自己)

    SCC+bitset+dp

    #include<bits/stdc++.h>
    using namespace std;
    
    // 方法:SCC + bitset传递闭包 或 直接bitset优化floyd
    /**
     * 1. tarjan板子复习
     * 2. tarjan缩点重建图复习
     * 3. 利用bitset求传递闭包(更快,因为可以直接按位或)
     * 4. bitset优化floyd
     */
    
    vector<int> h[2010]; // 原图的邻接表
    // tarjan需要的变量
    stack<int> stk;
    int dfn[2010], low[2010], instk[2010], idx; 
    int SCC[2010], cnt; // 每一个点所在的SCC编号、SCC的个数
    int SIZE[2010]; // 每一个SCC中包含的点数
    
    vector<int> scc[2010]; // 新图的邻接表
    bitset<2010> g[2010]; // 用于求新图的传递闭包的bitset对于每一个点开一个bitset, 传递闭包直接或
    
    void tarjan(int u){
        dfn[u] = low[u] = ++ idx;
        instk[u] = 1;
        stk.push(u);
        
        for(auto j : h[u]){
            if(!dfn[j]){
                tarjan(j);
                low[u] = min(low[u], low[j]);
            }else if(instk[j] && dfn[j] < low[u])
                low[u] = dfn[j];
        }
        
        if(low[u] == dfn[u]){
            cnt ++;
            int num = 0;
            do{
                num ++;
                int t = stk.top();
                SCC[t] = cnt;
                instk[t] = 0;
                stk.pop();
                if(t == u) break;
            }while(1);
            SIZE[cnt] = num; // 当前SCC中包含的点数
        }
    }
    
    bitset<2010> dfs(int u){
        if(g[u] != 0) return g[u];
        g[u][u] = 1;
        for(auto v : scc[u]){
            g[u] |= dfs(v);
        }
        return g[u];
    }
    
    void solve(){
        int n;
        cin >> n;
        // 建立原图的邻接表
        for(int i = 0; i < n; i ++){
            for(int j = 0; j < n; j ++){
                char c;
                cin >> c;
                if(c == '1') h[i].push_back(j);
            }
        }
        
        // SCC
    	for(int i = 0; i < n; i ++)
            if(dfn[i] == 0) tarjan(i);
       
        // 重建图,需要遍历所有边
        for(int i = 0; i < n; i ++){
            for(int j = 0; j < h[i].size(); j ++){
                if(SCC[i] != SCC[h[i][j]]) scc[SCC[i]].push_back(SCC[h[i][j]]);
            }
        }
        
        int ans = 0;
        for(int i = 1; i <= cnt; i ++){ // SCC是从1开始编号的
            auto k = dfs(i); // 求从i出发能到达的点的bitset
            for(int j = 1; j <= cnt; j ++) // 遍历bitset
                if(k[j])
                    ans += SIZE[i] * SIZE[j];
        }
        
        cout << ans << endl;
    }
    
    signed main(){
        solve();
    }
    

    bitset+floyd

    #include<bits/stdc++.h>
    using namespace std;
    
    bitset<2010> g[2010];
    
    void solve(){
        int n;
        cin >> n;
        for(int i = 0; i < n; i ++){
            string s;
            cin >> s;
            reverse(s.begin(), s.end());
            g[i] = bitset<2010>(s);
            g[i][i] = 1;
        }
        
        for(int k = 0; k < n; k ++)
            for(int i = 0; i < n; i ++)
                if(g[i][k]) g[i] |= g[k];
        
        int ans = 0;
        for(int i = 0; i < n; i ++){
            ans += g[i].count();
        }
        
        cout << ans << endl;
    }
    
    signed main(){
        solve();
    }
    
  • 相关阅读:
    Java总结篇系列:Java泛型
    视图、索引、存储过程优缺点
    SQL之case when then用法
    oracle数据库表的导入导出cmd命令大全
    ORA-01652:无法通过128(在表空间temp中)扩展temp段 解决方法
    如何查看一个数据文件是否是自动扩展
    ora-01652无法通过128(在表空间temp中)扩展temp段
    解决ora-01652无法通过128(在temp表空间中)扩展temp段的过程
    Java中的JDBC基础
    Java中的Property类
  • 原文地址:https://www.cnblogs.com/tomori/p/15618519.html
Copyright © 2011-2022 走看看