• BZOJ 2208[Jsoi2010]连通数


    题面:

    2208: [Jsoi2010]连通数

    Time Limit: 20 Sec  Memory Limit: 512 MB
    Submit: 3100  Solved: 1347
    [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。

    首先我们将图缩点,得到一个DAG。然后dfs暴力判断一个点可以到达那些点,然后统计答案。

      1 #include <iostream>
      2 #include <stdio.h>
      3 #include <string.h>
      4 #include <algorithm>
      5 using namespace std;
      6 #define maxm 2002
      7 #define maxn 2000001
      8 struct edge
      9 {
     10     int u,v,nex;
     11 }e[maxn];
     12 int pr[maxm],cnt;
     13 int CNT;
     14 inline void add(int u,int v)
     15 {
     16     e[++cnt]=(edge){u,v,pr[u]};
     17     pr[u]=cnt;
     18 }
     19 inline void ADD(int u,int v)
     20 {
     21     e[++CNT]=(edge){u,v,pr[u]};
     22     pr[u]=CNT;
     23 }
     24 int n;
     25 char s[maxm];
     26 int dfn[maxm],scc_cnt,scc_dfn,scc_size[maxm],belong[maxm],low[maxm];
     27 int st[maxm],top;
     28 bool vis[maxm];
     29 void tarjan(int u)
     30 {
     31     vis[u]=true;
     32     dfn[u]=low[u]=++scc_dfn;
     33     st[++top]=u;
     34     int v;
     35     for(int i=pr[u];i;i=e[i].nex)
     36     {
     37         v=e[i].v;
     38         if(!dfn[v])
     39         {
     40             tarjan(v);
     41             low[u]=min(low[u],low[v]);
     42         }
     43         else
     44             if(vis[v])
     45                 low[u]=min(low[u],dfn[v]);
     46     }
     47     if(dfn[u]==low[u])
     48     {
     49         int v=-1;
     50         ++scc_cnt;
     51         while(v!=u)
     52         {
     53             v=st[top--];
     54             vis[v]=false;
     55             belong[v]=scc_cnt;
     56             ++scc_size[scc_cnt];
     57         }
     58     }
     59 }
     60 void init()
     61 {
     62     for(int i=1;i<=n;i++)
     63         if(!dfn[i])
     64             tarjan(i);
     65     memset(pr,0,sizeof(pr));
     66     for(int i=1;i<=cnt;i++)
     67         if(belong[e[i].u]!=belong[e[i].v])
     68             ADD(belong[e[i].u],belong[e[i].v]);
     69 }
     70 int ans;
     71 void dfs(int u)
     72 {
     73     int v;
     74     ans+=scc_size[u];
     75     vis[u]=true;
     76     for(int i=pr[u];i;i=e[i].nex)
     77     {
     78         v=e[i].v;
     79         if(!vis[v])
     80             dfs(v);
     81     }
     82 }
     83 int main()
     84 {
     85     scanf("%d",&n);
     86     for(int i=1;i<=n;i++)
     87     {
     88         scanf("%s",s);
     89         for(int j=0;j<n;j++)
     90             if(s[j]=='1')
     91                 add(i,j+1);
     92     }
     93     init();
     94     int tot=0;
     95     for(int i=1;i<=scc_cnt;i++)
     96     {
     97         memset(vis,0,sizeof(vis));
     98         ans=0;
     99         dfs(i);
    100         tot+=ans*scc_size[i];
    101     }
    102     printf("%d",tot);
    103 }
    BZOJ 2208
  • 相关阅读:
    高精度模板 支持各种运算 c++
    404 页面不存在
    多柱汉诺塔问题“通解”——c++
    高精度gcd
    404 页面不存在
    如何开启音乐二倍速?不下载其他软件【win10】
    如何随时学习数学
    洛谷P1004 方格取数
    Title
    Title
  • 原文地址:https://www.cnblogs.com/radioteletscope/p/7588661.html
Copyright © 2020-2023  润新知