zoukankan      html  css  js  c++  java
  • UVa11324

    题目链接

    分析:
    不强制双向到达,求最大团
    显然一个强连通分量中的点要么都选,要么都不选
    我们可以用Tarjan把强连通分量缩点得到SCC图
    SCC图中每一个点的权值就是这个SCC中点的数量
    问题就转化成,
    在图中选择若干个点使得权值和最大
    求SCC图中的最大权路径

    由于SCC图是一个DAG,我们可以用dp来解决这个问题
    dp转移方程为f[x] = size[x] + max(f[y])

    tip

    第一次用vector存边,感觉挺好用的
    但是由于原图是稠密图,所以还是用邻接表存储较好

    TLE的原因是scc和pre数组一定要清零

    //这里写代码片
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<vector>
    #include<stack>
    #include<algorithm>
    
    using namespace std;
    
    const int N=1002;
    int n,m,scc[N],tot,low[N],pre[N],cnt,size[N];
    int f[N],in[N],st[N],tt;
    struct node{
        int y,nxt;
    };
    node way[50010];
    vector<int> G[N];
    stack<int> S;
    
    void add(int u,int w)
    {
        tt++;
        way[tt].y=w;way[tt].nxt=st[u];st[u]=tt;
    }
    
    void dfs(int now)
    {
        pre[now]=low[now]=++tot;
        S.push(now);   //
        for (int i=st[now];i;i=way[i].nxt)
        {
            int v=way[i].y;
            if (!pre[v])
            {
                dfs(v);
                low[now]=min(low[now],low[v]);
            }
            else if (!scc[v])
            {
                low[now]=min(low[now],pre[v]);
            }
        }
    
        if (low[now]==pre[now])
        {
            cnt++;
            int tt=0;
            for (;;)
            {
                int x=S.top();
                S.pop();
                scc[x]=cnt;
                tt++;
                if (x==now) break;
            }
            size[cnt]=tt;   //SCC的大小 
        }
    }
    
    void find()
    {
        memset(pre,0,sizeof(pre));
        memset(scc,0,sizeof(scc));
        while (!S.empty()) S.pop();
        tot=0; cnt=0;
        for (int i=1;i<=n;i++)
            if (!pre[i])
                dfs(i);
    }
    
    int dp(int now)
    {
        if (f[now]) return f[now];   //记忆化
        int ans=0;
        for (int i=0;i<G[now].size();i++)
        {
            int v=G[now][i];
            ans=max(ans,dp(v));
        } 
        f[now]=ans+size[now];
        return f[now];
    }
    
    void solve()
    {
        memset(in,0,sizeof(in));
        memset(f,0,sizeof(f));
        for (int i=1;i<=n;i++) G[i].clear(); 
    
        for (int i=1;i<=n;i++)
            for (int j=st[i];j;j=way[j].nxt)
            {
                int v=way[j].y;       //i--->v
                if (scc[i]!=scc[v])   //不在一个SCC中
                {
                    G[scc[i]].push_back(scc[v]);
                    in[scc[v]]++;
                } 
            }
    
        int ans=0;
        for (int i=1;i<=cnt;i++)
            if (!in[i])   //入度为0
               ans=max(ans,dp(i));
        printf("%d
    ",ans);
    }
    
    int main()
    {
        int T;
        scanf("%d",&T);
        while (T--)
        {
            memset(st,0,sizeof(st));
            tt=0;
    
            scanf("%d%d",&n,&m);
            for (int i=1;i<=m;i++)
            {
                int u,w;
                scanf("%d%d",&u,&w);
                add(u,w);
            }
    
            find();
    
            solve();
        }
        return 0;   
    }
  • 相关阅读:
    AC日记——[HNOI2008]GT考试 bzoj 1009
    AC日记——[SCOI2009]游戏 bzoj 1025
    AC日记——[HNOI2010]BOUNCE 弹飞绵羊 洛谷 P3203
    AC日记——旅游 bzoj 2157
    NOIP模拟2017.6.11解题报告
    AC日记——【模板】Link Cut Tree 洛谷 P3690
    AC日记——[SDOI2010]大陆争霸 洛谷 P3690
    [NOI2010]超级钢琴 倍增
    [HNOI2004]L语言 字典树 记忆化搜索
    对拍
  • 原文地址:https://www.cnblogs.com/wutongtong3117/p/7673011.html
Copyright © 2011-2022 走看看