P4306 [JSOI2010]连通数

Posted hahaha2124652975

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P4306 [JSOI2010]连通数相关的知识,希望对你有一定的参考价值。

题面

本题tj区一片大佬各种玄学算法,以至于我根本就没有办法去找代码对拍并让其不超时。。。

那么我的做法是先tarjan求强连通分量并缩点,同时记录此点中共包含了原图的多少点,及多少个点构成了强连通分量并缩成了该点,然后便利缩点后的图,运用记忆化记录该点是否被访问过,可以略微减少一点时间,但是仍有一个点1281ms超时,so等我有能力写出别的代码A掉这道题再来刷掉这道博客嘤嘤嘤

  1 #include<set>
  2 #include<map>
  3 #include<list>
  4 #include<queue>
  5 #include<stack>
  6 #include<string>
  7 #include<cmath>
  8 #include<ctime>
  9 #include<vector>
 10 #include<bitset>
 11 #include<memory>
 12 #include<utility>
 13 #include<cstdio>
 14 #include<sstream>
 15 #include<iostream>
 16 #include<cstdlib>
 17 #include<cstring>
 18 #include<algorithm>
 19 using namespace std;
 20 const int N=2005;
 21 
 22 stack <int> q;
 23 int n,tot,t,num,ans;
 24 int head[N],next[N],to[N],dfn[N],low[N],f[N],head2[N],next2[N],to2[N],cou[N];
 25 bool ok[N],visit[N];
 26 
 27 int mi(int a,int b)return a<b?a:b;
 28 int ma(int a,int b)return a>b?a:b;
 29 
 30 void add(int u,int v)//建图
 31     next[++tot]=head[u];
 32     head[u]=tot;
 33     to[tot]=v;
 34 
 35 
 36 void add2(int u,int v)//缩点后建图
 37     next2[++tot]=head2[u];
 38     head2[u]=tot;
 39     to2[tot]=v;
 40 
 41 
 42 void tarjan(int u)//tarjan模板
 43     dfn[u]=low[u]=++t;
 44     visit[u]=1;
 45     q.push(u);
 46     for(int i=head[u];i;i=next[i])
 47         if(!dfn[to[i]]&&ok[to[i]])
 48             tarjan(to[i]);
 49             low[u]=mi(low[u],low[to[i]]);
 50         
 51         else if(visit[to[i]])
 52             low[u]=mi(low[u],dfn[to[i]]);
 53         
 54     
 55     if(dfn[u]==low[u])
 56         int v,l=0;
 57         num++;
 58         do
 59             v=q.top();
 60             q.pop();
 61             visit[v]=0;
 62             f[v]=num;
 63             l++;
 64         while(v!=u);
 65         cou[num]=l;
 66     
 67 
 68 
 69 int mmp(int u)//递归求每个点的连通数
 70     ok[u]=1;
 71     for(int i=head2[u];i;i=next2[u])
 72         if(!ok[to2[i]])//该点没有求过
 73             cou[u]+=mmp(to2[i]);
 74         
 75         else//若以求过,则直接调用变量
 76             cou[u]+=cou[to2[i]];
 77         
 78     
 79     return cou[u];
 80 
 81 
 82 int main()
 83     scanf("%d",&n);
 84     for(int i=1;i<=n;i++)//读入
 85         char zy[N];
 86         cin>>zy+1;
 87         for(int j=1;j<=n;j++)
 88             if(zy[j]==1)
 89                 add(i,j);
 90                 ok[i]=ok[j]=true;
 91             
 92         
 93     
 94     for(int i=1;i<=n;i++)//遍历原图,缩点
 95         if(!dfn[i]&&ok[i])
 96             tarjan(i);
 97         
 98     
 99     tot=0;
100     for(int i=1;i<=n;i++)//对缩点后的图建图
101         if(ok[i])
102             for(int j=head[i];j;j=next[j])
103                 if(f[i]!=f[to[j]])
104                     add2(f[i],f[to[j]]);
105                 
106             
107         
108     
109     memset(ok,0,sizeof(ok));
110     for(int i=1;i<=num;i++)
111         int k=cou[i];//记录下该强连通分量中有多少个点,因为其可以互相达到对方,故这些点的连通数是一样的
112         ans+=k*mmp(i);
113         //printf("%d\n",ans);
114     
115     printf("%d\n",ans);//输出答案
116     return 0;
117 

再次申明,这段程序不能A掉着题,仅是提供一种思路(同时水一篇博客嘤嘤嘤),会在最后一个点超时

以上是关于P4306 [JSOI2010]连通数的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ 2208[Jsoi2010]连通数

bzoj2208[Jsoi2010]连通数

bzoj 2208: [Jsoi2010]连通数

bzoj2208 [Jsoi2010]连通数

bzoj2208: [Jsoi2010]连通数(dfs)

JSOI2010 连通数