zoukankan      html  css  js  c++  java
  • [题解]洛谷P3387 【模板】缩点

    背景

      这是一道tarjan缩点的模板题

    原题

      传送门

    思路

      没什么思路,先跑一遍tarjan,顺便记录每一个强联通分量(新点)的权值,将原图清0,然后遍历每一条边,如果这条边连接两个不同的强联通分量,就连一条边,最后记忆化搜索。

    代码

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<iostream>
    using namespace std;
    
    const int MAXN=10010,MAXM=100010;
    
    int n,m,ans=0,family[MAXN],fnum=0,val[MAXN],nval[MAXN]={0};
    int first[MAXN];
    
    struct edge{
        int u,v,next;
    }e[MAXM];
    
    int tot=0;
    void insert(int u,int v){
        tot++;e[tot].u=u;e[tot].v=v;e[tot].next=first[u];first[u]=tot;
    }
    
    int stack[MAXN],top=0;
    int deepdark=0;
    int dfn[MAXN]={0},low[MAXN]={0},ins[MAXN]={0};
    void tarjan(int u){
        dfn[u]=low[u]=++deepdark;
        ins[u]=1;
        top++;stack[top]=u;
        for(int i=first[u];i!=-1;i=e[i].next){
            int v=e[i].v;
            if(dfn[v]==0){
                tarjan(v);
                low[u]=min(low[u],low[v]);
            }
            else if(ins[v]){
                low[u]=min(low[u],dfn[v]);
            }
        }
        if(dfn[u]==low[u]){
            ++fnum;
            while(stack[top]!=u){
                family[stack[top]]=fnum;
                nval[fnum]+=val[stack[top]];
                ins[stack[top]]=0;
                top--;
            }
            family[u]=fnum;
            ins[u]=0;
            nval[fnum]+=val[u];
            top--;
        }
    }
    
    int f[MAXN]={0};
    void search(int u){
        if(f[u])return;
        f[u]=nval[u];
        int maxsum=0;
        for(int i=first[u];i!=-1;i=e[i].next){
            int v=e[i].v;
            search(v);
            maxsum=max(maxsum,f[v]);
        }
        f[u]+=maxsum;
    }
    
    int main(){
        memset(first,-1,sizeof(first));
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
            scanf("%d",&val[i]);
        int x,y;
        for(int i=1;i<=m;i++){
            scanf("%d%d",&x,&y);
            insert(x,y);
        }
        for(int i=1;i<=n;i++)if(dfn[i]==0)tarjan(i);
        tot=0;
        memset(first,-1,sizeof(first));
        //memset(e,0,sizeof(struct edge)*MAXM);
        for(int i=1;i<=m;i++){
            if(family[e[i].u]!=family[e[i].v]){
                insert(family[e[i].u],family[e[i].v]);
            }
        }
        for(int i=1;i<=fnum;i++){
            if(!f[i]){
                search(i);
                ans=max(ans,f[i]);
            }
        }
        printf("%d",ans);
        return 0;
    }
    本篇文章为SHINE_GEEK原创,转载请注明来源!
    written_by:SHINE_GEEK

    -------------------------------------
    签名:自己选的路,跪着也要走完;理想的实现,需要不懈奋斗!
    -------------------------------------
  • 相关阅读:
    100+ Python挑战性编程练习(1)
    python面试题--初级(二)
    python面试题--初级(一)
    centos查看iptables和firewall防火墙状态、开启、关闭防火墙
    Keepalived nginx HA负载均衡
    windows10安装SQLServer 2008 R2详细说明
    CentOS安装mysql5.7
    centOS7.5安装docker
    redis哨兵选举算法--raft
    CentOS7.5安装GitLab及汉化
  • 原文地址:https://www.cnblogs.com/sjrb/p/10341576.html
Copyright © 2011-2022 走看看