社区讨论

妹子刚学OI性感Tarjian在线求优化

P4306[JSOI2010] 连通数参与者 6已保存回复 15

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
15 条
当前快照
1 份
快照标识符
@lrrif28w
此快照首次捕获于
2024/01/24 16:14
2 年前
此快照最后确认于
2024/01/24 17:05
2 年前
查看原帖
rt,T了一个点,已用bitset优化,求优化,如果做法有误也请点出,我是按照第三篇题解调的。
CPP
#include<iostream>
#include<queue>
#include<bitset>
#include<cstring>
#include<map>
using namespace std;
struct Edge{
    int l,nxt;
}edges[5000005],ed[5000005];
string s;
int n,m,tt=1,ttt=1,head[2005],h[2005];
int ans,du[2005],vu[2005];
int tot,dfn[2005],low[2005];
int top,stk[2005],instk[2005];
int cnt,scc[2005],scs[2005];
map<pair<int,int>,int> mo;
queue<int> qo;
bitset<20005> anu[2005];
void add_edge(int f,int l){
    tt+=1;
    edges[tt]={l,head[f]};
    head[f]=tt;
}
void add1(int f,int l){
    ttt+=1;
    ed[ttt]={l,h[f]};
    h[f]=ttt;
}
void tarjian(int x){
    tot+=1,top+=1;
    dfn[x]=low[x]=tot;
    instk[x]=1,stk[top]=x;
    for(int i=head[x];i;i=edges[i].nxt){
        int l=edges[i].l;
        if(!low[l]){
            tarjian(l);
            low[x]=min(low[x],low[l]);
        }
        else if(instk[l]) low[x]=min(low[x],dfn[l]);
    }
    if(low[x]==dfn[x]){
        int y;cnt+=1;
        do{
            y=stk[top],top-=1,instk[y]=0;
            scc[y]=cnt,scs[cnt]+=1;
        }while(y!=x);
    }
}
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>s;
         for(int j=0;j<s.size();j++){
            if(s[j]=='1'){
                add_edge(i,j+1);
            }
        }
    }
    for(int i=1;i<=n;i++) if(!dfn[i]) tarjian(i);
    for(int f=1;f<=n;f++){
        for(int i=head[f];i;i=edges[i].nxt){
            int l=edges[i].l;
            if(scc[f]==scc[l]||mo[{scc[f],scc[l]}]) continue;
            mo[{scc[f],scc[l]}]=1;
            add1(scc[l],scc[f]);
            du[scc[f]]+=1;//从后更新前
        }
    }
    for(int i=1;i<=cnt;i++){
        if(!du[i]) qo.push(i);
        anu[i][i]=1;
    }
    while(!qo.empty()){
        int x=qo.front();qo.pop();
        for(int i=h[x];i;i=ed[i].nxt){
            int l=ed[i].l;
            anu[l]|=anu[x];
            du[l]-=1;
            if(!du[l]) qo.push(l);
        }
    }
    for(int i=1;i<=cnt;i++){
        for(int j=1;j<=cnt;j++){
            if(anu[i][j]==1) ans+=scs[i]*scs[j];
        }
    }
    cout<<ans;
    return 0;
}

回复

15 条回复,欢迎继续交流。

正在加载回复...