首先有向图的题目不难想到先tarjan缩点

一个强连通分量中的点的连通数显然是相等;

据说这样直接dfs就可以过了,但显然不够精益求精

万一给定的是一个完全的DAG图怎么办,dfs铁定超时;

首先想,dfs进行了很多不必要的操作,比如说i--->j

那么j的连通数一定也是i的连通数,但我们做dfs是需要做两遍的,降低了效率

那么为了提高效率,我们希望支持一个这样的操作

记录下每个点所能到的点,并且能快速的合并;

不由的想到位运算,但是最多只有30位,而实际有2000个点怎么办?

那我们就维护最多70个数,每个数表示到达情况

dp[k,i]为一个表示连通状况的数

第i个数的二进制上第j个位置(位置从右往左,0~30) 代表点k能否到达点(i-1)*30+j+1 (1代表可到达,0代表不可)

然后从出度为0的点不断dp即可;

具体见程序,表达不清,时间复杂度大约是O(nm/30) 还是非常优秀的

 type link=^node;
     node=record
       po:longint;
       next:link;
     end; var edge,way:array[..] of link;
    v,f:array[..] of boolean;
    be,count,dfn,low,st:array[..] of longint;
    dp:array[..,..] of longint;
    ans,s,state,h,t,l,x,y,i,j,n,m:longint;
    ch:ansistring;
    p:link; function min(a,b:longint):longint;
  begin
    if a>b then exit(b) else exit(a);
  end; procedure add(y:longint;var q:link);
  var p:link;
  begin
    new(p);
    p^.po:=y;
    p^.next:=q;
    q:=p;
  end; procedure tarjan(x:longint);
  var y:longint;
      p:link;
  begin
    p:=edge[x];
    v[x]:=true;
    f[x]:=true;
    inc(h);
    dfn[x]:=h;
    low[x]:=h;
    inc(t);
    st[t]:=x;
    while p<>nil do
    begin
      y:=p^.po;
      if not v[y] then
      begin
        tarjan(y);
        low[x]:=min(low[x],low[y]);
      end
      else if f[y] then
        low[x]:=min(low[x],low[y]);
      p:=p^.next;
    end;
    if low[x]=dfn[x] then
    begin
      inc(s);
      while st[t+]<>x do
      begin
        y:=st[t];
        f[y]:=false;
        be[y]:=s;
        inc(count[s]);
        dec(t);
      end;
    end;
  end; procedure merge(x,y:longint);   //合并点的连通情况
  var i,j:longint;
  begin
    for i:= to state do
      dp[x,i]:=dp[x,i] or dp[y,i];
  end; function get(x:longint):longint;  
  var i,j,r:longint;
  begin
    get:=;
    for i:= to state do  //穷举每个数
      for j:= to do   //穷举二进制的每一位
      begin
        r:= shl j;    //位运算的技巧
        if r>dp[x,i] then break;  
        if (dp[x,i] and r)<> then
          get:=get+count[(i-)*+j+]; 
      end;
  end; begin
  readln(n);
  for i:= to n do
  begin
    readln(ch);
    for j:= to n do
    begin
      x:=ord(ch[j])-;
      if x<> then add(j,edge[i]);
    end;
  end;
  for i:= to n do
    if not v[i] then
    begin
      h:=;
      t:=;
      tarjan(i);
    end;   fillchar(dfn,sizeof(dfn),);
  for i:= to n do
  begin
    p:=edge[i];
    while p<>nil do
    begin
      y:=p^.po;
      if be[y]<>be[i] then
      begin
        inc(dfn[be[i]]);      //计算出度
        add(be[i],way[be[y]]);   //缩点后记录点be[y]被那些点指向
      end;
      p:=p^.next;
    end;
  end;
  fillchar(v,sizeof(v),false);
  t:=;
  for i:= to s do
    edge[i]:=nil;
  for i:= to s do
  begin
    p:=way[i];
    while p<>nil do
    begin
      x:=p^.po;
      add(i,edge[x]);   //记录点i指向那些点
      p:=p^.next;
    end;
    x:=(i-) div +;
    y:=(i-) mod ;
    dp[i,x]:= shl y;   //每个点对自己都是可达的
  end;
  for i:= to s do
    if dfn[i]= then   //从出度为0的点开始dp
    begin
      inc(t);
      st[t]:=i;
    end;   state:=s div +;
  l:=;
  while l<=t do
  begin
    inc(l);
    x:=st[l];
    p:=edge[x];
    while p<>nil do
    begin
      y:=p^.po;
      merge(x,y);   //每个x指向的点的连通数一定也是x的连通数,合并
      p:=p^.next;
    end;
    ans:=ans+count[x]*get(x);  //计算连通数
    p:=way[x];
    while p<>nil do     //类似拓扑排序,删除点x,寻找新的出度为0的点
    begin
      y:=p^.po;
      dec(dfn[y]);
      if dfn[y]= then
      begin
        inc(t);
        st[t]:=y;
      end;
      p:=p^.next;
    end;
  end;
  writeln(ans);
end.

bzoj2208的更多相关文章

  1. 【BZOJ2208】[JSOI2010]连通数(Tarjan)

    [BZOJ2208][JSOI2010]连通数(Tarjan) 题面 BZOJ 洛谷 题解 先吐槽辣鸡洛谷数据,我写了个\(O(nm)\)的都过了. #include<iostream> ...

  2. 【BZOJ2208】[Jsoi2010]连通数 DFS

    [BZOJ2208][Jsoi2010]连通数 Description Input 输入数据第一行是图顶点的数量,一个正整数N. 接下来N行,每行N个字符.第i行第j列的1表示顶点i到j有边,0则表示 ...

  3. [bzoj2208][Jsoi2010]连通数_bitset_传递闭包floyd

    连通数 bzoj-2208 Jsoi-2010 题目大意:给定一个n个节点的有向图,问每个节点可以到达的点的个数和. 注释:$1\le n\le 2000$. 想法:网上有好多tarjan+拓扑序dp ...

  4. BZOJ2208: [Jsoi2010]连通数

    tarjan缩点后拓扑排序,每一个点用一个bitset记录哪些点能到达它. PS:数据太水,暴力能过. #include<bits/stdc++.h> using namespace st ...

  5. bzoj2208:[Jsoi2010]连通数

    http://blog.csdn.net/u013598409/article/details/47037499 里面似乎有生成数据的... //我本来的想法是tarjan缩点之后然后将图遍历一遍就可 ...

  6. bzoj2208 [Jsoi2010]连通数(scc+bitset)

    2208: [Jsoi2010]连通数 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 1879  Solved: 778[Submit][Status ...

  7. 【BZOJ2208】【JSOI2010】连通数 传递闭包

    题目描述 定义一个图的连通度为图中可达顶点对的数目.给你一个\(n\)个点的有向图,问你这个图的连通度. \(n\leq 2000,m\leq n^2\) 题解 一个很简单的做法就是传递闭包:像flo ...

  8. bzoj2208 连通数(bitset优化传递闭包)

    题目链接 思路 floyd求一下传递闭包,然后统计每个点可以到达的点数. 会tle,用bitset优化一下.将floyd的最后一层枚举变成bitset. 代码 /* * @Author: wxyww ...

  9. BZOJ2208: [Jsoi2010]连通数(tarjan bitset floyd)

    题意 题目链接 Sol 数据水的一批,\(O(n^3)\)暴力可过 实际上只要bitset优化一下floyd复杂度就是对的了(\(O(\frac{n^3}{32})\)) 还可以缩点之后bitset维 ...

随机推荐

  1. android测试的相关概念以及单元测试

    1.测试的相关概念  1.根据是否知道源代码分类: 黑盒测试: a - b - c  边值测试    白盒测试: 根据源代码写测试方法 或者 测试用例; 2.根据测试的粒度分类: 方法测试:写完一个方 ...

  2. 什么是SQL statement?

    什么是SQL statement? 1.SQL SELECT statement - SELECT命令 REFER: What is SQL, and what are some example st ...

  3. android开发之GenyMotion与intelliJ的配置

    (注意:这是在你的电脑上安装了intelliJ和安卓SDK后才进行的工作,如果没有intelliJ和安卓SDK,请先安装以上两样东西) 号称史上最快乐的模拟器GenyMotion,试一下. 第一步:下 ...

  4. 【nodemailer】 之邮件附件

    nodemailer 续 之前对nodemailer做了一个简单的了解,这篇文章主要研究一下如何添加附加文件 测试代码 //Created by yyrdl on 2015/10/2. var nod ...

  5. RX学习笔记:在FreeCodeCamp的学习

    FreeCodeCamp https://www.freecodecamp.com 2016-07-03 前几日在Github浏览时,偶然看到一个叫FreeCodeCamp的开源项目,进去该网站之后感 ...

  6. javascript基础DOM操作

    DOM 中的三个字母,D(文档)可以理解为整个 Web 加载的网页文档:O(对象)可以理解为类似 window 对象之类的东西,可以调用属性和方法,这里我们说的是 document对象:M(模型)可以 ...

  7. 微信video标签全屏无法退出bug

    安卓(android)微信里面video播放视频,会被强制全屏,播放完毕后还有腾讯推荐的视频,非常讨厌..强制被全屏无法解决,但是视频播放完毕后退出播放器可以解决.方法就是视频播放完毕后,用音频aud ...

  8. linux批量修改文件名的shell脚本

    linux中批量修改文件名的shell脚本代码,主要是使用了rename,结合shell,喜欢的朋友可以参考下 使用 rename 命令  ========================  NAME ...

  9. Windows系统下Oracle数据库冷备

    一.背景: 具体的场景是数据库不是普通的OLTP系统,更像是OLAP系统,数据的更新频率很低,在noarchivelog 模式下运行,实时性要求低,但是数据只有一份不能弄丢,需要应付磁盘损坏等情况.这 ...

  10. 利用数据库链做DML操作时报ORA-02069: global_names parameter must be set to TRUE for this operation

    按照 http://space.itpub.net/195110/viewspace-711110 的说法顺利解决问题. 通过DBLink更新远程数据的时候,如果使用到本地的sequence.函数.过 ...