BZOJ 2208 [Jsoi2010]连通数

来源:互联网 发布:大数据平台优势 编辑:程序博客网 时间:2024/06/05 10:45

缩点+bitset+DP

先缩点。每一块的答案是他能到达的(包括自己)所有块的siz和自己的siz相乘的和,于是对缩点后的拓扑图进行DP即可。

#include<cstdio>#include<queue>#include<bitset>#include<algorithm>#define N 2005using namespace std;bitset<N> f[N];queue<int> q;char s[N];int ecnt=1, belong[N], last[N], last2[N], dfn[N], low[N], t, st[N], top, tot, siz[N], in[N];;struct edge{int next,to;}e[N*N*2];void add(int a, int b){    e[++ecnt]=(edge){last[a],b};    last[a]=ecnt;}void add2(int a, int b){    e[++ecnt]=(edge){last2[a],b};    last2[a]=ecnt;}void tarjan(int x){    st[++top]=x;    low[x]=dfn[x]=++t;    for(int i = last[x]; i; i=e[i].next)    {        int y=e[i].to;        if(dfn[y] && !belong[y])low[x]=min(low[x],dfn[y]);//有向图需要记下belong,表示虽然能搜到,但是独立它成一个连通块,所以不能贡献         else if(!dfn[y]){tarjan(y);low[x]=min(low[x],low[y]);}    }    if(dfn[x]==low[x])    {        tot++;        siz[tot]=1;        while(st[top]!=x)        {            siz[tot]++;            belong[st[top]]=tot;            top--;        }        belong[x]=tot;        top--;    }}int main(){    int n;    scanf("%d",&n);    for(int i = 1; i <= n; i++)    {        scanf("%s",s+1);        for(int j = 1; j <= n; j++)            if(s[j]=='1')                add(i,j);    }    for(int i = 1; i <= n; i++)        if(!dfn[i])            tarjan(i);    for(int x = 1; x <= n; x++)        for(int i = last[x]; i; i=e[i].next)        {            int y=e[i].to;            if(belong[x]!=belong[y])            {                add2(belong[y],belong[x]);                in[belong[x]]++;            }        }    for(int i = 1; i <= tot; i++)    {        if(!in[i])        {            q.push(i);        }        f[i][i]=1;    }    while(!q.empty())    {        int x=q.front();        q.pop();        for(int i = last2[x]; i; i=e[i].next)        {            int y=e[i].to;            f[y]|=f[x];            in[y]--;            if(!in[y])q.push(y);        }    }    int ans=0;    for(int i = 1; i <= tot; i++)        for(int j = 1; j <= tot; j++)            if(f[i][j])            {                ans+=siz[i]*siz[j];            }    printf("%d\n",ans);}
0 0
原创粉丝点击