zoukankan      html  css  js  c++  java
  • [bzoj2208][Jsoi2010]连通数

    一道传递闭包裸题。tarjan+拓扑dp也很强而且貌似更快。本来想写的。

    然而查题解的时候发现一个博主的一句话引起了我的共鸣。

    bzoj上这道题rank前面都是1500B+的大佬,很快,几百ms,到了1600ms,,就发现了许多600B左右的代码。
    后面还有10s+的不知道咋做的。bitset也没加吧(毕竟数据太小了)。

    果断Floyd-Warshall传递闭包+bitset水过。


    靠题面是jpg啊

    Input

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

    Output

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

    Sample Input

    3
    010
    001
    100

    Sample Output

    9

    HINT

    对于100%的数据,N不超过2000。


    顺便复习传递闭包(OI里的)。好像离散数学有啥玩意我当然是不会啦。

    传递闭包就是说给你有向图一个(01矩阵还是边集都行),问两点是否可达。(因为是有向图所以存在A能到B反之不可的情况)。

    首先把给的信息建成一个邻接矩阵。

    开局只有一个01矩阵,能不能求出正解全看造化你会不会。

    其实很简单。Floyd求最短路会叭,直接跑一遍。只要两点之间距离不是inf就说明可达呗!

    有点炎爆砸帕奇斯的感觉。因为只是求是否可达,就不需要初始化成inf再跑最短路,

    只要$f[i][j]=1$即i可达j,那么j能到的i必然也能到,所以直接在$f[i]$的bitset上再或一个$f[j]$的bitset。

    至于循环顺序,和Floyd最短路一样,不知道为啥记住就好咯。


    贴代码

    #include<bits/stdc++.h>
    using namespace std;
    const int mxn=2010;
    bitset<mxn>g[mxn];
    int main(){
        int n;scanf("%d",&n);
        char s[mxn];
        for(int i=1;i<=n;i++){
            scanf("%s",s+1);
            for(int j=1;j<=n;j++)
            g[i][j]=s[j]-'0';
            g[i][i]=1;
        }
        for(int k=1;k<=n;k++)
        for(int i=1;i<=n;i++)
        if(g[i][k])g[i]|=g[k];
        int ans=0;
        for(int i=1;i<=n;i++)
        ans+=g[i].count();
        printf("%d",ans);
    }
  • 相关阅读:
    git
    oracle object_id和data_object_id的区别
    statspack系列8
    statspack系列7
    statspack系列6
    statspack系列5
    statspack系列4
    statspack系列3
    statspack系列2
    MySQL源码之两阶段提交
  • 原文地址:https://www.cnblogs.com/orzzz/p/7472550.html
Copyright © 2011-2022 走看看