zoukankan      html  css  js  c++  java
  • Tarjan求强联通分量

    hihocoder1185

    题意

    中文题

    分析

    SCC后剩下的缩点都是scc[i]=i,若最后剩下n个点,并不一定是1~n

    第一种:拓扑排序,对每一个点以其为终点的最大值

    第二种:dfs记忆化搜索,对每一个点以其为起点的最大值

    显然第二种更简单易写

    dfs记忆化搜索

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn =  1e5 + 5;
    const int INF = 0x3f3f3f3f;
    
    stack<int>s;
    bool vis[maxn];
    int dfn[maxn],low[maxn],scc[maxn],idx;
    vector<int>g[maxn],newp[maxn];
    int n,m,u,v,w[maxn],answer[maxn];
    
    void tarjan(int u)
    {
        dfn[u]=low[u]=++idx;
        s.push(u);
        vis[u]=true;
        int v;
        for(int i=0;i<g[u].size();++i){
            v=g[u][i];
            if(dfn[v]==0){
                tarjan(v);
                low[u]=min(low[u],low[v]);
            }else if(vis[v])
                low[u]=min(low[u],dfn[v]);
        }
        if(dfn[u]==low[u])
            do{
                v=s.top();
                s.pop();
                scc[v]=u;//指向根节点
                vis[v]=false;
            }while(u!=v);
    }
    
    void suodian()
    {
        for(int i=1;i<=n;i++)
        {
            int len=g[i].size();
            for(int j=0;j<len;j++)
            {
                int to=g[i][j];
                if(scc[i]==to||w[to]==0)
                    continue;
                if(scc[to]!=to)
                    w[scc[to]]+=w[to],w[to]=0;
                else newp[scc[i]].push_back(to);
            }
        }
    }
    
    
    int d[maxn];
    int ans;
    
    int dfs(int x)
    {
        if(answer[x])
        {
            //cout<<answer[x]<<endl;
            return answer[x];
        }
    
        int len=newp[x].size();
        if(len==0)
            return answer[x]=w[x];
        for(int i=0;i<len;i++)
        {
            int to=newp[x][i];
            int t=dfs(to);
            answer[x]=max(answer[x],w[x]+answer[to]);
        }
    }
    
    int main()
    {
        ios::sync_with_stdio(false);
        cin>>n>>m;
        for(int i=1;i<=n;i++)
            cin>>w[i];
        for(int i=1;i<=m;i++)
        {
            cin>>u>>v;
            g[u].push_back(v);
        }
        for(int i=1;i<=n;i++)
            scc[i]=i;
        tarjan(1);
        suodian();
        memset(vis,false,sizeof(vis));
        dfs(scc[1]);
        printf("%d
    ",answer[scc[1]]);
        return 0;
    }
    View Code

    拓扑排序

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn =  1e5 + 5;
    const int INF = 0x3f3f3f3f;
    
    stack<int>s;
    bool vis[maxn];
    int dfn[maxn],low[maxn],scc[maxn],idx;
    vector<int>g[maxn],newp[maxn];
    int n,m,u,v,w[maxn],answer[maxn];
    
    void tarjan(int u)
    {
        dfn[u]=low[u]=++idx;
        s.push(u);
        vis[u]=true;
        int v;
        for(int i=0;i<g[u].size();++i){
            v=g[u][i];
            if(dfn[v]==0){
                tarjan(v);
                low[u]=min(low[u],low[v]);
            }else if(vis[v])
                low[u]=min(low[u],dfn[v]);
        }
        if(dfn[u]==low[u])
            do{
                v=s.top();
                s.pop();
                scc[v]=u;//指向根节点
                vis[v]=false;
            }while(u!=v);
    }
    
    void suodian()
    {
        for(int i=1;i<=n;i++)
        {
            int len=g[i].size();
            for(int j=0;j<len;j++)
            {
                int to=g[i][j];
                if(scc[i]==to||w[to]==0)
                    continue;
                if(scc[to]!=to)
                    w[scc[to]]+=w[to],w[to]=0;
                else newp[scc[i]].push_back(to);
            }
        }
    }
    
    
    int d[maxn];
    
    void dfs(int x)
    {
        vis[x]=1;
        int len=newp[x].size();
        for(int i=0;i<len;i++)
        {
            int to=newp[x][i];
            d[to]++;
            if(!vis[to])
            dfs(to);
        }
    }
    queue<int>q;
    int ans;
    
    void tpsort(int x)
    {
        q.push(x);
        answer[x]=w[x];
        while(!q.empty())
        {
            //cout<<123<<endl;
            int now=q.front();
            q.pop();
            ans=max(ans,answer[now]);
            int len=newp[now].size();
            for(int i=0;i<len;i++)
            {
                int to=newp[now][i];
               // cout<<to<<' '<<scc[to]<<endl;
                answer[to]=max(answer[to],w[to]+answer[now]); ///
                d[to]--;
                if(d[to]==0)
                    q.push(to);
            }
        }
    }
    
    int main()
    {
        ios::sync_with_stdio(false);
        cin>>n>>m;
        for(int i=1;i<=n;i++)
            cin>>w[i];
        for(int i=1;i<=m;i++)
        {
            cin>>u>>v;
            g[u].push_back(v);
        }
        for(int i=1;i<=n;i++)
            scc[i]=i;
        tarjan(1);
        suodian();
        memset(vis,false,sizeof(vis));
        dfs(scc[1]);
        tpsort(scc[1]);
        printf("%d
    ",ans);
        return 0;
    }
    View Code
  • 相关阅读:
    C,LINUX,数据结构部分
    LINUX应用开发工程师职位(含答案)
    INT32 System_UserKeyFilter(NVTEVT evt, UINT32 paramNum, UINT32 *paramArray)
    屏幕调试
    1.ARM嵌入式体系结构与接口技术(Cortex-A8版)
    NT9666X调试log
    DemoKit编译过程错误
    selenium 代理设置
    pandas 轮询dataframe
    Spring 定时任务
  • 原文地址:https://www.cnblogs.com/Superwalker/p/8894071.html
Copyright © 2011-2022 走看看