bzoj2208连通数

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

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。

题解

先tarjan缩点,然后对于两个连通的连通块,显然其对答案的贡献为sum[i]*sum[j],sum为块中节点个数

代码

#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<queue>
#include<algorithm>
#define N 2010
using namespace std;
int head[N],next[N*N],to[N*N];
int Head[N],Next[N*N],To[N*N];
int dfn[N],low[N],belong[N],c[N],s[N],num[N];
int sum,p,q,g,top,n,f,ans;
bool vis[N];
char S[N];
queue<int>Q;
void link(int x,int y) {next[++sum]=head[x]; head[x]=sum; to[sum]=y;}
void Link(int x,int y) {Next[++sum]=Head[x]; Head[x]=sum; To[sum]=y;}
void tarjan(int p)
{
    dfn[p]=low[p]=++sum; s[++top]=p; vis[p]=true;
    for (int i=head[p];i;i=next[i])
        {
            int v=to[i];
            if (!dfn[v]) {tarjan(v); low[p]=min(low[p],low[v]);}
            else if (vis[v]) low[p]=min(low[p],dfn[v]);
        }
    if (dfn[p]==low[p])
        {
            do
                {
                    q=s[top--]; vis[q]=false;
                    belong[q]=p; num[p]++;
                } while(p!=q);
            ans+=num[p]*num[p];
        }
}
void dfs(int p)
{
    for (int j=Head[p];j;j=Next[j])
        if (!c[To[j]]) Q.push(To[j]),c[To[j]]=1,ans+=f*num[To[j]],dfs(To[j]);
}
int main()
{
    freopen("1.in","r",stdin);
    freopen("1.out","w",stdout);
    scanf("%d",&n);
    for (int i=1;i<=n;i++)
        {
            scanf("%s",S);
            for (int j=0;j<=n-1;j++)
                if (S[j]=='1') link(i,j+1);
        }

    sum=0;
    for (int i=1;i<=n;i++)
        if (!dfn[i]) tarjan(i);

    sum=0;
    for (int i=1;i<=n;i++)
        for (int j=head[i];j;j=next[j])
            if (belong[i]!=belong[to[j]]) Link(belong[i],belong[to[j]]);

    for (int i=1;i<=n;i++)
        if (belong[i]==i)
            {
                while (!Q.empty()) {g=Q.front(); c[g]=0; Q.pop();}
                f=num[i]; dfs(i);
            }

    printf("%d\n",ans);
    return 0;
}

 

posted @ 2016-10-17 16:15  xiaoqiang200015  阅读(182)  评论(0编辑  收藏  举报