• BZOJ2208 [JSOI2010] 连通数


    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2208

    Description

    Input

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

    Output

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

    Tarjan缩点+拓扑排序+bitset,mark[i][j]中的i表示第i个强连通分量,每一个点j对应mark[i][j/30+1]从右边数起第j%30位。

    每一个点与一个强连通分量连通的答案贡献值等于该强连通分量的大小

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <algorithm>
     4 #include <cstring>
     5 #include <stack>
     6 #include <queue>
     7 #define rep(i,l,r) for(int i=l; i<=r; i++)
     8 #define clr(x,y) memset(x,y,sizeof(x))
     9 #define travel(x) for(int i=last[x]; i; i=edge[i].pre)
    10 #define travel2(x) for(int i=last2[x]; i; i=edge2[i].pre)
    11 using namespace std;
    12 const int maxn = 2010;
    13 struct Edge{
    14     int pre,to;
    15 }edge[maxn*maxn],edge2[maxn*maxn];
    16 int n,m,x,now,maxx,tot=0,tot2=0,ans=0,scc=0,dfsclock=0;
    17 int last[maxn],last2[maxn],dfn[maxn],low[maxn],belong[maxn],cnt[maxn],ind[maxn],mark[maxn][70];
    18 char ch[maxn];
    19 bool isin[maxn];
    20 stack <int> s;
    21 queue <int> q;
    22 inline void addedge(int x,int y){
    23     edge[++tot].pre = last[x];
    24     edge[tot].to = y;
    25     last[x] = tot;
    26 }
    27 inline void addedge2(int x,int y){
    28     edge2[++tot2].pre = last2[x];
    29     edge2[tot2].to = y;
    30     last2[x] = tot2;
    31     ind[y]++;
    32 }
    33 void tarjan(int x){
    34     dfn[x] = low[x] = ++dfsclock;
    35     isin[x] = 1; s.push(x);
    36     travel(x){
    37         if (!dfn[edge[i].to]){
    38             tarjan(edge[i].to);
    39             low[x] = min(low[x],low[edge[i].to]);
    40         }
    41         else if (isin[edge[i].to]) low[x] = min(low[x],dfn[edge[i].to]);
    42     }
    43     if (dfn[x] == low[x]){
    44         scc++;
    45         while (s.top() != x){
    46             isin[s.top()] = 0;
    47             belong[s.top()] = scc;
    48             cnt[scc]++;
    49             s.pop();
    50         }
    51         isin[x] = 0; belong[x] = scc; cnt[scc]++; s.pop();
    52     }
    53 }
    54 void toposort(){
    55     clr(mark,0);
    56     rep(i,1,n) mark[belong[i]][i/30+1] |= (1 << (i % 30));
    57     rep(i,1,scc) if (!ind[i]) q.push(i);
    58     while (!q.empty()){
    59         now = q.front(); q.pop();
    60         travel2(now){
    61             rep(j,1,maxx) mark[edge2[i].to][j] |= mark[now][j];
    62             ind[edge2[i].to]--;
    63             if (!ind[edge2[i].to]) q.push(edge2[i].to);
    64         }
    65     }
    66 }
    67 int main(){
    68     scanf("%d",&n); clr(last,0); clr(last2,0); clr(mark,0); maxx = n / 30 + 1;
    69     rep(i,1,n){
    70         scanf("%s",ch);
    71         rep(j,1,n) if (ch[j-1] - '0') addedge(i,j);
    72     }
    73     clr(isin,0); clr(dfn,0); clr(cnt,0);
    74     rep(i,1,n) if (!dfn[i]) tarjan(i);
    75     clr(ind,0);
    76     rep(now,1,n) travel(now) if (belong[now] != belong[edge[i].to])
    77         addedge2(belong[now],belong[edge[i].to]);
    78     toposort();
    79     rep(i,1,scc) rep(j,1,n)
    80     if (mark[i][j/30+1] & (1 << (j % 30))) ans += cnt[i];
    81     printf("%d
    ",ans);
    82     return 0;
    83 }
    View Code
  • 相关阅读:
    矩阵
    字符串算法 KMP算法 BF算法的升级版
    字符查找算法 BF算法
    查找:二叉查找树升级版 平衡二叉树(AVL树) 2020年8月
    查找:二叉查找树 c++ 2020年8月
    基数排序,也叫关键码排序
    归并排序,冯诺依曼首次提出。分为递归实现、非递归实现
    堆排序,升级版的选择排序
    P1233 木棍加工【dp】
    P2758 编辑距离【dp】
  • 原文地址:https://www.cnblogs.com/jimzeng/p/bzoj2208.html
Copyright © 2020-2023  润新知