zoukankan      html  css  js  c++  java
  • UVA

    题目要求一个最大的弱联通图。

    首先对于原图进行强连通缩点,得到新图,这个新图呈链状,类似树结构。

    对新图进行记忆化dp,求一条权值最长的链,每一个点的权值就是当前强连通分量点的个数。


    /*
    Tarjan算法求有向图的强连通分量set记录了强连通分量
    Col记录了强连通分量的个数。
    */
    #include <iostream>
    #include<cstring>
    #include<cstdio>
    #include<string>
    #include<algorithm>
    using namespace std;
    #define MAXN 2005
    #define MAXM 100005
    struct node
    {
        int to,next;
    }edge[MAXM],edge2[MAXM];
    bool have[1005][1005];
    int sums[1005];
    int head[MAXN],head2[MAXN],en,en2;
    bool root[MAXN];
    int low[MAXN],dfn[MAXN],stack[MAXN],top,set[MAXN],col,num;
    bool vis[MAXN],instack[MAXN];
    int dp[MAXN];
    int n;
    int m;
    void addedge(int a,int b)
    {
        edge[en].to=b;
        edge[en].next=head[a];
        head[a]=en++;
    }
    void addedge2(int a,int b)
    {
        edge2[en2].to=b;
        edge2[en2].next=head2[a];
        head2[a]=en2++;
    }
    void tarjan(int u)
    {
    
        vis[u]=1;
        dfn[u]=low[u]=++num;
        instack[u]=true;
        stack[++top]=u;
        for(int i=head[u];i!=-1;i=edge[i].next)
        {
            int v=edge[i].to;
            if(!vis[v])
            {
                tarjan(v);
                low[u]=min(low[u],low[v]);
            }
            else
                if(instack[v])
                    low[u]=min(dfn[v],low[u]);
        }
        if(dfn[u]==low[u])
        {
            int j;
            col++;
            do
            {
                j=stack[top--];
                instack[j]=false;
              set[j]=col;
            }
            while (j!=u);
        }
    }
    void init()
    {
        int i;
        en=en2=top=col=num=0;
        memset(head,-1,sizeof(head));
        memset(head2,-1,sizeof(head2));
        memset(instack,0,sizeof(instack));
        memset(vis,0,sizeof(vis));
        memset(set,-1,sizeof(set));
        memset(have,0,sizeof(have));
        memset(sums,0,sizeof(sums));
        memset(root,true,sizeof(root));
        memset(dp,-1,sizeof(dp));
    }
    int ans;
    int dfs(int now,int fa)
    {
        if(~dp[now]) return dp[now];
        int maxs=sums[now];
        for(int i=head2[now];~i;i=edge2[i].next)
        {
            int to=edge2[i].to;
            if(to!=fa)
            {
                maxs=max(maxs,sums[now]+dfs(to,now));
            }
        }
        return dp[now]=maxs;
    }
    int main()
    {
        int a,b;
        int cas;
        scanf("%d",&cas);
        while(cas--)
        {
            scanf("%d%d",&n,&m);
            init();
            for(int i=1;i<=m;i++)
            {
                scanf("%d%d",&a,&b);
                addedge(a,b);
            }
            for(int i=1;i<=n;i++)
                if(!vis[i])tarjan(i);
            for(int i=1;i<=n;i++)
            {
                sums[set[i]]++;
                for(int j=head[i];~j;j=edge[j].next)
                {
                    int to=edge[j].to;
                    if(set[i]!=set[to]&&!have[set[i]][set[to]])
                    {
                        addedge2(set[i],set[to]);
                        root[set[to]]=false;
                        have[set[i]][set[to]]=have[set[to]][set[i]]=true;
                    }
                }
            }
            ans=0;
            for(int i=1;i<=col;i++)
            {
                if(root[i])
                {
                    dfs(i,-1);
                    ans=max(ans,dp[i]);
                }
            }
            printf("%d
    ",ans);
        }
        return 0;
    }


  • 相关阅读:
    python note 30 断点续传
    python note 29 线程创建
    python note 28 socketserver
    python note 27 粘包
    python note 26 socket
    python note 25 约束
    Sed 用法
    python note 24 反射
    python note 23 组合
    python note 22 面向对象成员
  • 原文地址:https://www.cnblogs.com/zfyouxi/p/4499384.html
Copyright © 2011-2022 走看看