Number of communication BZOJ2208

It was quite simple tarjan.

When the determination may be repeated, to get direct bitset.

First tarjan shrink points within each scc sure to reach each other and more about, and a contribution scc where each point is certainly the same, topsort, update the answer on it, with a count bitset into the scc size to .

It is said that data is water, about O (n ^ 3) can be had, but I looked, did not shrink point, direct dfs, more detail, a little tired of the algorithm is relatively long, but smaller than the brain. It is still relatively good, tarjan and cooked just 15min to get topsort played.

#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<vector>
#include<queue>
#include<stack>
#include<bitset>
#include<map>
using namespace std;
struct EDGE{
    int ed,nex;
}edge[4000050],edgec[4000050];
int num,numc,ans,first[3000],firstc[3000];
int n,ord,sccnum,top;
sta [you1000000],dfn[3000],low[3000],bl[3000],du[3000];
char ch[3000];
bool ins[3000];
vector<int>scc[3000];
bitset<3000>s[3000];
void add(int st,int ed){
//    cout<<"st="<<st<<" ed="<<ed<<endl;
    edge[++num].ed=ed;
    edge[num].nex=first[st];
    first[st]=num;
}
void addc(int st,int ed){
//    cout<<"Stc="<<st<<" edc="<<ed<<endl;
    edgec[++numc].ed=ed;
    edgec[numc].nex=firstc[st];
    firstc[st]=numc;
}
void tarjan(int x){
    dfn[x]=low[x]=++ord;
    sta[++top]=x;ins[x]=1;
    for(int i=first[x];i;i=edge[i].nex){
        int y=edge[i].ed;
        if(!dfn[y]){
            tarjan(y);
            low[x]=min(low[x],low[y]);
        }else if(ins[y])
            low[x]=min(low[x],dfn[y]);
    }if(dfn[x]==low[x]){
        sccnum++;int p;
        do{
            p=sta[top--];ins[p]=0;
            bl[p]=sccnum;scc[sccnum].push_back(p);
        }while(p!=x);
    }
}
void topsort(){
    queue<int>q;
    for(int i=1;i<=sccnum;i++)
        if(du[i]==0) q.push(i);
    while(!q.empty()){
        int x=q.front();q.pop();
    //    cout<<x<<" ";
        for(int i=firstc[x];i;i=edgec[i].nex){
            int y=edgec[i].ed;
            du[y]--;
            s[y]|=s[x];
            if(du[y]==0)
                q.push(y);
        }
    }
}
int main(){
//    freopen("a,in","r",stdin);
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%s",ch+1);
        for(int j=1;j<=n;j++)
            if(ch[j]-'0')
                add(i,j);
    }
    for(int i=1;i<=n;i++)
        if(!dfn[i]) tarjan(i);
    for(int i=1;i<=n;i++)
        for(int j=first[i];j;j=edge[j].nex){
            int y=edge[j].ed;
            if(bl[i]==bl[y]) continue;
            addc(bl[i],bl[y]);
            du[bl[y]]++;
        }
    for(int i=1;i<=sccnum;i++){
        for(int j=0;j<scc[i].size();j++){
            int y=scc[i][j];
            s[i][y]=1;
        }        
    }
    topsort();
    for(int i=1;i<=sccnum;i++)
        ans+=s[i].count()*scc[i].size();
    printf("%d\n",ans);
    return 0;
}
View Code

 

Guess you like

Origin www.cnblogs.com/Yu-shi/p/11183135.html