bzoj 2208: [Jsoi2010]连通数

来源:互联网 发布:pci串行端口 感叹号 编辑:程序博客网 时间:2024/06/05 04:52

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

第一轮


先tarjan缩点,然后对于每个点都dfs寻找可以到达的联通块。然后加一加就好了

明明想囤题的= =结果还是算了。。为了AC数量写题写不下去。。。

#include<cstdio>#include<string>#include<cstring>using namespace std;int n;struct map{     int s,t;     int next;}a[4000001],exa[4000001];int edge,exedge;int head[10001],exhead[10001];int scc,cnt;bool v[10001];int s[10001],top;int dfn[10001],low[10001],belong[10001];int sx[10001];int map[2001][2001];inline void add(int s,int t){ a[edge].next=head[s];     head[s]=edge;     a[edge].s=s;     a[edge].t=t;}inline void exadd(int s,int t){ exa[exedge].next=exhead[s];     exhead[s]=exedge;     exa[exedge].s=s;     exa[exedge].t=t;}inline int min(int x,int y){     if(x<y)          return x;     return y;}inline void tarjan(int d){     int i,x;     cnt++;     dfn[d]=cnt;     low[d]=cnt;     top++;     s[top]=d;     v[d]=true;     for(i=head[d];i!=0;i=a[i].next)     {       x=a[i].t;          if(dfn[x]==0)          {               tarjan(x);               low[d]=min(low[d],low[x]);          }          else if(v[x]&&low[d]>dfn[x])//v在栈中,修改low[u]               low[d]=dfn[x];     }     if(dfn[d]==low[d])//u为该强连通分量中遍历所成树的根     {          scc++;          x=s[top];          top--;          while(x!=d)          {       v[x]=false;               belong[x]=scc;               x=s[top];               top--;          }          v[x]=false;          belong[x]=scc;     }}inline void count_edge(){ int i,j,d;     for(i=1;i<=n;i++)     {       sx[belong[i]]++;          for(j=head[i];j!=0;j=a[j].next)          {               d=a[j].t;               if(belong[i]!=belong[d]&&map[belong[i]][belong[d]]!=1)               {                    exedge++;                    exadd(belong[i],belong[d]);                    map[belong[i]][belong[d]]=1;               }          }     }}inline int dfs(int d){ v[d]=true;     int sum=sx[d];     int i;     for(i=exhead[d];i!=0;i=exa[i].next)     {          int t=exa[i].t;          if(!v[t])               sum+=dfs(t);     }     return sum;}char x[10001];int main(){     scanf("%d",&n);     int i,j;     for(i=1;i<=n;i++)     {          scanf("%s",x);          for(j=0;j<=n-1;j++)          {               if(x[j]=='1')               {                    edge++;                    add(i,j+1);               }          }     }     for(i=1;i<=n;i++)          if(dfn[i]==0)               tarjan(i);     count_edge();     int ans=0;     for(i=1;i<=n;i++)     {          memset(v,false,sizeof(v));          ans+=dfs(belong[i]);     }     printf("%d\n",ans);     return 0;}


0 0