zoukankan      html  css  js  c++  java
  • Tarjan 缩点

    //tarjan 缩点 
    //把强连通分量染成同样的颜色 用数组记录一下强连通分量内所有点权和 
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    int n,m,cnt,ans,head[10001];
    int t,sta[10001],vis[10001];
    int dot,dfn[10001],low[10001];
    int val[10001],a[200001],b[200001],ma[10001];
    int    tot,col[10001],sum[10001]; 
    struct uio{
        int to,next;
    }edge[200001];
    void add(int x,int y)
    {
        edge[++cnt].next=head[x];
        edge[cnt].to=y;
        head[x]=cnt;
    }
    void tarjan(int x)
    {
        dfn[x]=low[x]=++dot;
        sta[++t]=x;
        vis[x]=1;
        for(int i=head[x];i;i=edge[i].next)
        {
            int y=edge[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])
        {
            tot++;
            while(sta[t+1]!=x) 
            {
                col[sta[t]]=tot;
                sum[tot]+=val[sta[t]];
                vis[sta[t]]=0;
                t--;
            }
        }
    }
    void get(int x)
    {
        if(ma[x])
            return;
        ma[x]=sum[x];
        int manum=0;
        for(int i=head[x];i;i=edge[i].next)
        {
            int y=edge[i].to;
            if(!ma[y])
                get(y);
            manum=max(manum,ma[y]);
        }
        ma[x]+=manum;
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
            scanf("%d",&val[i]);
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d",&a[i],&b[i]);
            add(a[i],b[i]);
        }
        for(int i=1;i<=n;i++)
            if(!dfn[i])
                tarjan(i);
        memset(head,0,sizeof(head));
        memset(edge,0,sizeof(edge));
        cnt=0;
        for(int i=1;i<=m;i++)
            if(col[a[i]]!=col[b[i]])
                add(col[a[i]],col[b[i]]);
        for(int i=1;i<=tot;i++)
            if(!ma[i])
            {
                get(i);
                ans=max(ans,ma[i]);
            }
        printf("%d
    ",ans);
         return 0;
    }
  • 相关阅读:
    shell面试题整理
    用循环链表实现Josephus问题
    in与exists的区别
    单链表的建立/测长/打印/删除/排序/逆序/寻找中间值
    float在内存中的存放
    crontab定时任务详解
    螺旋队列问题之二
    螺旋队列问题之一
    android网络编程--从网络下载图片,并保存到内存卡
    android Shader类简介_渲染图像示例
  • 原文地址:https://www.cnblogs.com/water-radish/p/9280529.html
Copyright © 2011-2022 走看看