zoukankan      html  css  js  c++  java
  • ZOJ3795_Grouping

    告诉你某些人的年龄大小关系,问你把所有的人分成若干个组,最少需要多少组,使得组内任意两个人的年龄不可比。

    首先考虑特殊情况,如果所有年龄关系构成了一个环,那么这个环中所有人的年龄都是相等,也就是可比的。

    同时所有其他的与这个环中任意一个点相连的任意一个环或者点都是可比的。

    如果两个点或者环,无法处在同一条路径上,那么这两个点和环就是不可比的。

    于是算法就出来了。

    对于每一个强连通分量,我们将其缩为一个点,点权为这个连通分量中的点数。这样就相当于我们找一条权值最大的路径就好了。

    由于缩点后一定是一个有向无环图,那么可以通过dp或者记忆化搜索解决问题。

    召唤代码君:

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <vector>
    #define maxn 600600
    using namespace std;
    
    vector<int> V[maxn];
    int to[maxn],next[maxn],first[maxn],edge;
    int d[maxn],f[maxn],low[maxn],belong[maxn],ans;
    int stack[maxn],top;
    int n,m,sccnum,dfs_clock;
    
    void _init()
    {
        edge=ans=0;
        top=sccnum=0;
        memset(first,-1,sizeof(int)*(n+2));
        memset(d,0,sizeof(int)*(n+2));
        memset(belong,0,sizeof(int)*(n+2));
    }
    
    void addedge(int U,int V)
    {
        if (U==V) return;
        to[edge]=V,next[edge]=first[U],first[U]=edge++;
    }
    
    void dfs(int cur)
    {
        d[cur]=low[cur]=++dfs_clock;
        stack[++top]=cur;
        for (int i=first[cur]; i!=-1; i=next[i])
            if (!d[to[i]]){
                dfs(to[i]);
                low[cur]=min(low[cur],low[to[i]]);
            }
            else if (!belong[to[i]]) low[cur]=min(low[cur],d[to[i]]);
        if (low[cur]==d[cur]){
            V[++sccnum].clear();
            f[sccnum]=0;
            for (;;){
                int x=stack[top--];
                belong[x]=sccnum;
                f[sccnum]++;
                if (x==cur) break;
            }
        }
    }
    
    int get(int x)
    {
        if (d[x]!=-1) return d[x];
        d[x]=0;
        for (unsigned i=0; i<V[x].size(); i++)
            d[x]=max(get(V[x][i]),d[x]);
        return d[x]=d[x]+f[x];
    }
    
    int main()
    {
        int UU,VV;
        while (scanf("%d%d",&n,&m)!=EOF){
            _init();
            while (m--){
                scanf("%d%d",&UU,&VV);
                addedge(UU,VV);
            }
            for (int i=1; i<=n; i++)
                if (!d[i]) dfs(i);
            for (int i=1; i<=n; i++)
                for (int j=first[i]; j!=-1; j=next[j])
                    if (belong[i]!=belong[to[j]])
                        V[belong[i]].push_back(belong[to[j]]);
            memset(d,-1,sizeof(int)*(sccnum+2));
            for (int i=1; i<=sccnum; i++)
                ans=max(ans,get(i));
            printf("%d
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    #虚树,树形dp#CF613D Kingdom and its Cities
    #搜索,容斥#洛谷 2567 [SCOI2010]幸运数字
    #三分#洛谷 5931 [清华集训2015]灯泡
    windows中日期自动替换
    oracle的tablespaces使用情况监控
    k8s配置master运行pod
    redis配置数据持久化
    Centos7清理僵尸进程
    ZOJ 1078 Palindrom Numbers
    OCP 071【中文】考试题库(cuug整理)第33题
  • 原文地址:https://www.cnblogs.com/lochan/p/3894132.html
Copyright © 2011-2022 走看看