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

    http://blog.csdn.net/u013598409/article/details/47037499 里面似乎有生成数据的。。。
    //我本来的想法是tarjan缩点之后然后将图遍历一遍就可以了,复杂度应该是O(n2)的,为什么说这样是n3的啊。。。
    //=>这种做法是错的因为有可能会重复计算用一下传递闭包就可以了然而直接递推以前写的dfsqaq
    #include<cstdio>
    #include<cstring>
    #include<cctype>
    #include<algorithm>
    #include<stack>
    #include<vector>
    #include<queue>
    #include<bitset>
    using namespace std;
    #define rep(i,s,t) for(int i=s;i<=t;i++)
    #define dwn(i,s,t) for(int i=s;i>=t;i--)
    #define clr(x,c) memset(x,c,sizeof(x))
    #define qwq(x) for(edge *o=head[x];o;o=o->next)
    const int nmax=2e3+5;
    const int maxn=nmax*nmax;
    const int inf=0x7f7f7f7f;
    struct edge{
        int to;edge *next;
    }; 
    edge es[maxn],*pt=es,*head[nmax];
    void add(int u,int v){
        pt->to=v;pt->next=head[u];head[u]=pt++;
    }
    char ch[nmax];
    int pre[nmax],scc_cnt,dfs_clock,sm[nmax],scc[nmax];
    stack<int>s;
    void mins(int &a,int b){
        if(a>b) a=b;
    }
    int dfs(int x){
        int lowu=pre[x]=++dfs_clock;s.push(x);
        qwq(x){
            if(!pre[o->to]) mins(lowu,dfs(o->to));
            if(!scc[o->to]) mins(lowu,pre[o->to]);
        }
        if(lowu==pre[x]){
            scc_cnt++;int o,cnt=0;
            while(1){
                o=s.top();s.pop();
                scc[o]=scc_cnt;++cnt;
                if(o==x) break;
            }
            sm[scc_cnt]=cnt;
        }
        return lowu;
    }
    bitset<nmax>a[nmax];
    int in[nmax];vector<int>g[nmax];queue<int>q;
    int main(){
        int n,u,v,d;scanf("%d",&n);
        rep(i,1,n){
            scanf("%s",ch+1);
            rep(j,1,n) if(ch[j]=='1') add(i,j);
        }
        rep(i,1,n) if(!pre[i]) dfs(i);
         
        rep(i,1,n) {
            u=scc[i];
            qwq(i) if(u!=(v=scc[o->to])) g[u].push_back(v),++in[v];
        }
        rep(i,1,scc_cnt) a[i][i]=1;
        rep(i,1,scc_cnt) if(!in[i]) q.push(i);
        while(!q.empty()){
            u=q.front();q.pop();
            if(!g[u].size()) continue;
            rep(i,0,g[u].size()-1){
                v=g[u][i];
                a[v]|=a[u]; //a保存的是可以到达该强联通分量的 
                if(!--in[v]) q.push(v);
            }
        }
        int ans=0;
        rep(i,1,scc_cnt) rep(j,1,scc_cnt) if(a[i][j]) ans+=sm[i]*sm[j];
        printf("%d
    ",ans);
        return 0;
    }
    

    2208: [Jsoi2010]连通数

    Time Limit: 20 Sec  Memory Limit: 512 MB
    Submit: 2249  Solved: 965
    [Submit][Status][Discuss]

    Description

    Input

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

    Output

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

    Sample Input

    3
    010
    001
    100

    Sample Output

    9

    HINT

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

    Source

    [Submit][Status][Discuss]
  • 相关阅读:
    使用vue3.0仿Mac系统的提醒事项做的一个TODO功能
    一些容易忽略的css选择器
    根据node节点生成VNode以及解析成node节点
    jQuery-day02
    jQuery-day01
    初探WebSocket
    Python-如何对字典集合进行排序
    sqlserver获取代理服务作业job的执行情况
    excel中多表汇总
    [javascript][转载]jQuery获取Select选择的Text和 Value
  • 原文地址:https://www.cnblogs.com/fighting-to-the-end/p/5858060.html
Copyright © 2011-2022 走看看