[tarjan+bitset]BZOJ 2208——[Jsoi2010]连通数

来源:互联网 发布:网络机顶盒检测 编辑:程序博客网 时间:2024/06/05 07:35

2208: [Jsoi2010]连通数

题目描述

这里写图片描述

解题报告

这题的题目描述非常清晰,看到网上有dalao用bitset优化Floyd就过了。博主用tarjan缩点然后用bitset优化传递闭包就可以。

但是看到很多人缩点完刷拓扑啊,其实这个操作很鸡肋。学过2sat应该有所了解,拓扑序就是tarjan刷出来的scc序(画个图就知道了)。

然后最后刷答案的时候注意一下就可以了,我开了两个数组,一个是或起来之后当前节点的状态,一个是原来的状态,这样的操作使调用bitset的次数变多,所以效率很低(3000ms+)。
希望各位dalao能告诉我更优的方法。

#include<cstdio>#include<bitset>#include<algorithm>using namespace std;const int maxn=2005,maxm=4000005;int tot[2],lnk[maxn][2],son[maxm][2],nxt[maxm][2],x[maxn];int n,top,s[maxn],G,scc[maxn],low[maxn],dfn[maxn],tim,ans;bool ins[maxn],vis[maxn][maxn];bitset<maxn> a[maxn],b[maxn];void add(int x,int y,int id){    nxt[++tot[id]][id]=lnk[x][id];lnk[x][id]=tot[id];son[tot[id]][id]=y;}inline char _read(){    char ch=getchar();    while (ch!='0'&&ch!='1') ch=getchar();    return ch;}void tarjan(int x){    dfn[x]=++tim;low[x]=tim;    s[++top]=x;ins[x]=1;    for (int j=lnk[x][0];j;j=nxt[j][0])    if (!dfn[son[j][0]]){tarjan(son[j][0]);low[x]=min(low[x],low[son[j][0]]);}    else if (ins[son[j][0]]) low[x]=min(low[x],dfn[son[j][0]]);    if (dfn[x]==low[x]){        G++;        while (s[top]!=x) scc[s[top]]=G,ins[s[top]]=0,a[G][s[top--]]=1;        scc[x]=G;ins[x]=0;a[G][x]=1;top--;    }}void maker(){    for (int i=1;i<=n;i++)    for (int j=lnk[i][0];j;j=nxt[j][0])    if (scc[i]>scc[son[j][0]]&&!vis[scc[i]][scc[son[j][0]]])    add(scc[i],scc[son[j][0]],1),vis[scc[i]][scc[son[j][0]]];}int main(){    freopen("exam.in","r",stdin);    freopen("exam.out","w",stdout);    scanf("%d",&n);    for (int i=1;i<=n;i++)    for (int j=1;j<=n;j++)    if (_read()=='1') add(i,j,0);    for (int i=1;i<=n;i++) if (!dfn[i]) tarjan(i);    for (int i=1;i<=G;i++) x[i]=a[i].count();    maker();    for (int i=1;i<=G;i++) b[i]=a[i];    for (int i=G;i>=1;i--){        int y=b[i].count();ans+=x[i]*x[i];        for (int j=lnk[i][1];j;j=nxt[j][1]){            ans+=(y-(b[i]&b[son[j][1]]).count())*x[son[j][1]];            b[son[j][1]]=b[son[j][1]]|b[i];        }    }    printf("%d\n",ans);    return 0;}
原创粉丝点击