• luogu_3387【题解】缩点 tarjan


    题目:https://www.luogu.org/problemnew/show/P3387

    如题目描述,缩点加DP

    怎么缩点????

    tarjan算法,主要在于维护了一个low[ ] 数组。

    low 数组表示一个点可以到达的最浅的点的dfs序。

    如果一个点的low[ ]数组与自己的dfs序相等,证明自己整个子树是强连通分量。

    强连通分量就可以缩成一个点。

    tarjan代码如下(来源:洛谷网校课件)

    int s[MAXN], stop;
    int dfn[MAXN], low[MAXN];
    int scccnt, sccnum[MAXN];
    int dfscnt;
    
    inline void tarjan(int now){
        dfn[now] = low[now] = ++dfscnt;
        s[stop++] = now;
        for (int i = he[now]; i != 0 ; i = ne[i]){
            if (!dfn[ed[i]]) {
                tarjan(ed[i]);
                low[now] = min(low[now], low[ed[i]]);
            } else if(!sccnum[ed[i]]) {
                low[now] = min(low[now], dfn[ed[i]]);
            }
        }
    
        if (dfn[now] == low[now]) {
            scccnt++;
            do {
                sccnum[s[--stop]] = scccnt;
            } while(s[stop] != now);
        }
    }

    这个代码中,sccnum[ ]存的就是缩后的点的顺序。(重新排列了。)

    下个代码则是,sccnum[ ]存的缩之前强连通分量的最浅的点的编号,也就是now。

    代码如下。

    int s[maxn], stop;
    int dfn[maxn],low[maxn],dfscnt,sccnum[maxn];
    inline void tarjan(int now){
        dfn[now]=low[now]=++dfscnt;
        s[stop++]=now;
        for(int i=head[now];i;i=nxt[i]){
            int t=to[i];
            if(!dfn[t]){
                tarjan(t);
                low[now]=min(low[now],low[t]);
            }else if(!sccnum[t]){
                low[now]=min(low[now],dfn[t]);
            }
        }
        if(dfn[now]==low[now]){
            do{
                int t=s[--stop];
                sccnum[t]=now;   //主要区别。
                if(now!=t)
                    d[now]+=d[t];
            }while(s[stop]!=now);
        }
    }

    那么这道题也就可以解决了。

    DP则简单。

    就是重新在缩点之后连边,从子节点中更新。

    代码如下。

    #include<bits/stdc++.h>
    #define sc(x) scanf("%d",&x)
    using namespace std;
    const int maxn=1e4+10,maxm=1e5+10;
    int n,m,tot;
    int d[maxn],head[maxm],nxt[maxm<<1],to[maxm<<1],from[maxm<<1];
    inline void add(int u,int v){
        to[++tot]=v,from[tot]=u;
        nxt[tot]=head[u],head[u]=tot;
    }
    int s[maxn], stop;
    int dfn[maxn],low[maxn],dfscnt,sccnum[maxn];
    inline void tarjan(int now){
        dfn[now]=low[now]=++dfscnt;
        s[stop++]=now;
        for(int i=head[now];i;i=nxt[i]){
            int t=to[i];
            if(!dfn[t]){
                tarjan(t);
                low[now]=min(low[now],low[t]);
            }else if(!sccnum[t]){
                low[now]=min(low[now],dfn[t]);
            }
        }
        if(dfn[now]==low[now]){
            do{
                int t=s[--stop];
                sccnum[t]=now;   
                if(now!=t)
                    d[now]+=d[t];
            }while(s[stop]!=now);
        }
    }
    struct node{
        int from,to,nxt;
    }e[maxm<<1];
    int he[maxm],cnt,du[maxn],ans,dis[maxn];
    inline void topo()
    {
        queue<int> q;
        for(int i=1;i<=n;i++)
            if(sccnum[i]==i&&!du[i]){
                q.push(i);dis[i]=d[i];
            }
        while(!q.empty()){
            int k=q.front();q.pop();
            for(int i=he[k];i;i=e[i].nxt){
                int t=e[i].to;
                dis[t]=max(dis[t],dis[k]+d[t]);
                if(!--du[t]) q.push(t);
            }
        }
        for(int i=1;i<=n;i++)
            ans=max(ans,dis[i]);
    }
    int main()
    {
        sc(n),sc(m);
        for(int i=1;i<=n;i++)
            sc(d[i]);
        for(int i=1;i<=m;i++){
            int u,v;
            sc(u),sc(v);
            add(u,v);
        }
        for(int i=1;i<=n;i++) 
            if(!dfn[i]) tarjan(i);
        for(int i=1;i<=m;i++){
            int u=sccnum[from[i]],v=sccnum[to[i]];
            if(u!=v){
                e[++cnt].from=u;
                e[cnt].to=v;
                e[cnt].nxt=he[u];
                he[u]=cnt;
                du[v]++;
            }
        }
        topo();
        printf("%d
    ",ans);
        system("pause");
        return 0;
    }
  • 相关阅读:
    设置tomcat访问根路径
    关于Java抽象类的理解
    JavaIO
    synchronized关键字
    Java线程池
    Codeforces1478F-Nezzar and Nice Beatmap
    Codeforces1477B-Nezzar and Binary String
    Codeforces1476D Journey
    Codeforces1478D Nezzar and Board
    Codeforces Round #697 (Div. 3)G. Strange Beauty
  • 原文地址:https://www.cnblogs.com/ChrisKKK/p/10976542.html
Copyright © 2020-2023  润新知