zoukankan      html  css  js  c++  java
  • Tarjan

    有向图强连通分量SCC

    P3387【模板】缩点
    注释放代码里啦
    时间复杂度O(n+m)

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #define maxn 100010
    #define maxm 1000010
    using namespace std;
    template<typename T>
    inline void read(T &x){
        x=0;bool flag=0;char c=getchar();
        for(;!isdigit(c);c=getchar()) if(c=='-') flag=1;
        for(;isdigit(c);c=getchar()) x=x*10+(c^48);
        if(flag) x=-x;
    }
    
    int n,m,w[maxn],x[maxm],y[maxm];//因为重新建图还要用到,所以x,y要拿数组存 
    int cnt,head[maxn];
    int dfn[maxn],low[maxn],co[maxn],v[maxn],val[maxn];//dfn时间戳,low追溯值
    int top,st[maxn],siz[maxn],f[maxn],ans,dfncnt,cocnt;//st栈,f记搜 
    bool vis[maxn];//判断该点在不在栈中 
    struct node{
        int nxt;
        int to;
    }e[2*maxn];
    
    void add(int from,int to){
        e[++cnt].to=to;
        e[cnt].nxt=head[from];
        head[from]=cnt;
    }
    
    void tarjan(int x){
        dfn[x]=low[x]=++dfncnt;
        st[++top]=x;
        vis[x]=1;
        for(int i=head[x];i;i=e[i].nxt){
            int y=e[i].to;
            if(!dfn[y]){
                tarjan(y);
                low[x]=min(low[x],low[y]);
            }
            else{
                if(vis[y]) low[x]=min(low[x],dfn[y]);//********
            }
        }
        if(low[x]==dfn[x]){
            cocnt++;//cocnt记录整张图的强连通分量个数 
            int now;
            do{
                now=st[top];
                top--;
                vis[now]=0;
                co[now]=cocnt;//co[now]表示now所在的强连通分量编号 
                val[cocnt]+=v[now];
            }while(now!=x);
        }
    }
    
    void clear(){
        cnt=0;
        for(int i=1;i<=m;i++) head[i]=0,e[i].nxt=0,e[i].to=0;
    }
    
    void dfs(int x){//在DAG上记忆化搜索 
        if(f[x]) return ;
        f[x]=val[x];
        int maxx=0;
        for(int i=head[x];i;i=e[i].nxt){
            int y=e[i].to;
            if(!f[y]) dfs(y);
            maxx=max(maxx,f[y]);
        }
        f[x]+=maxx;
    }
    
    int main(){
        read(n),read(m);
        for(int i=1;i<=n;i++) read(v[i]);
        for(int i=1;i<=m;i++) read(x[i]),read(y[i]),add(x[i],y[i]);//建原图 
        for(int i=1;i<=n;i++) if(!dfn[i]) tarjan(i);
        clear();//把原图清空 
        for(int i=1;i<=m;i++) if(co[x[i]]!=co[y[i]]) add(co[x[i]],co[y[i]]);//重新建图,如果这条边的两点不在一个强连通分量里,就连上这条边 
        for(int i=1;i<=cocnt;i++){
            if(!f[i]) dfs(i);
            ans=max(ans,f[i]);
        }
        cout<<ans<<endl;
        return 0;
    }
    
  • 相关阅读:
    redis主从同步
    redis持久化
    redis发布订阅
    mariadb主从复制,
    nginx+uwsgi+django+virtualenv+supervisor发布web服务器
    Oracle 11gR2 RAC Installation on Oracle Linux 6.5
    ORA-1555 causes and solutions
    Linux实时查看日志的四种命令详解
    Linux查看日志常用命令
    oracle 11g 静默安装
  • 原文地址:https://www.cnblogs.com/DReamLion/p/14746432.html
Copyright © 2011-2022 走看看