ZOJ 3795 Grouping

Grouping


Time Limit: 2 Seconds      Memory Limit: 65536 KB


Suppose there are N people in ZJU, whose ages are unknown. We have some messages about them. The i-th message shows that the age of person si is not smaller than the age of person ti. Now we need to divide all these N people into several groups. One‘s age shouldn‘t be compared with each other in the same group, directly or indirectly. And everyone should be assigned to one and only one group. The task is to calculate the minimum number of groups that meet the requirement.

Input

There are multiple test cases. For each test case: The first line contains two integers N(1≤ N≤ 100000), M(1≤ M≤ 300000), N is the number of people, and M is is the number of messages. Then followed by M lines, each line contain two integers si and ti. There is a blank line between every two cases. Process to the end of input.

Output

For each the case, print the minimum number of groups that meet the requirement one line.

Sample Input

4 4
1 2
1 3
2 4
3 4

Sample Output

3

Hint

set1= {1}, set2= {2, 3}, set3= {4}

题目给出N个点 , M条边, 然后问一些相关联的人(存在一条路u -> v)不能分在同一组 , 最少分的组的数目 。

这样肯定要求一个  scc ..  那么在同一个scc里面的人(假设有w个人)都要拆分成w组 , 那么我们以这个w作为

scc图的点权 。 目的是所有 scc图(DAG) 的最长路所构成的权 ,取最大。

最长路用一个记忆化搜索即可 , 训练的时候不会这么用 , 卡蒙了~~ 。

#include <bits/stdc++.h>
using namespace std;
const int N = 100010;

int pre[N] , lowlink[N] , sccno[N] , dfs1_clock , scc_cnt ;
stack<int>st;
int n , m ;
int w[N] , dep_w[N];
bool vis[N];
int in[N];
int dp[N];

int eh[N] , et[N<<2] ,nxt[N<<2] , tot ;

void addedge( int u , int v )
{
    et[tot] = v , nxt[tot] = eh[u] , eh[u] = tot ++ ;
}

struct node
{
    int u , v ;
}e[N*3];

void dfs1( int u )
{
    pre[u] = lowlink[u] = ++dfs1_clock;
    st.push(u);
    for( int i = eh[u]; ~i ; i = nxt[i] ){
        int v = et[i] ;
        if(!pre[v]){
            dfs1(v);
            lowlink[u] = min(lowlink[u],lowlink[v]);
        }
        else if( !sccno[v] ){
            lowlink[u] = min( lowlink[u] , pre[v] );
        }
    }
    if( lowlink[u] == pre[u] )
    {
        scc_cnt++;
        for(;;){
            int  x = st.top(); st.pop();
            sccno[x] = scc_cnt ;
            if( x == u ) break;
        }
    }
}

void find_scc()
{
    dfs1_clock = scc_cnt = 0 ;
    memset ( pre , 0 , sizeof pre ) ;
    memset ( sccno , 0 , sizeof sccno ) ;
    while( !st.empty() ) st.pop();

    for( int i = 1 ; i <= n ; ++i ){
        if( !pre[i] )dfs1(i);
    }
}

void init()
{

    tot= 0 ;
    memset( eh , -1 ,sizeof eh );
    memset( dp , -1 ,sizeof dp );
    memset( w , 0 ,sizeof w );
    memset( vis ,false , sizeof vis );
    memset( in , 0, sizeof in );
}

void dfs( int u )
{
    if( dp[u] == -1 ){
        int sum_now = w[u] ;
        for( int i = eh[u] ; ~i ; i = nxt[i] ){
            int v = et[i];
            dfs(v);
            sum_now = max( sum_now , w[u] + dp[v] );
        }
        dp[u] = sum_now;
    }
}

void run()
{
    int u , v ;
    init();
    for( int i = 0 ; i < m ;++i ){
        scanf("%d%d",&e[i].u,&e[i].v);
        addedge( e[i].u , e[i].v );
    }
    find_scc();
    tot = 0 ;
    memset(eh , -1 , sizeof eh );

    for( int i = 0 ;i < m ;++i ){
        if( sccno[e[i].u] != sccno[e[i].v] ){
            addedge(  sccno[e[i].u] , sccno[e[i].v] );
            in[ sccno[e[i].v] ] ++;
        }
    }

    for( int i = 1 ; i <= n ; ++i  )w[ sccno[i] ] ++ ;
    int ans = 0 ;
    for( int i = 1 ; i <= scc_cnt ; ++i ) if( !in[i] ) addedge(0,i);
    dfs(0);
    for( int i = 1; i <= scc_cnt ; ++i ) ans = max( ans , dp[i] );
    printf("%d\n",ans);
}

int main()
{
    #ifdef LOCAL
    freopen("in","r",stdin);
    #endif
    ios::sync_with_stdio(0);
    while( ~scanf("%d%d",&n,&m))run();
}
时间: 2024-10-10 04:18:23

ZOJ 3795 Grouping的相关文章

ZOJ 3795 Grouping 强连通分量-tarjan

一开始我还天真的一遍DFS求出最长链以为就可以了 不过发现存在有向环,即强连通分量SCC,有向环里的每个点都是可比的,都要分别给个集合才行,最后应该把这些强连通分量缩成一个点,最后保证图里是 有向无环图才行,这个时候再找最长链,当然缩点之后的scc是有权值的,不能只看成1,缩点完了之后,用记忆化搜索DP就可以再On的复杂度内求出结果 所以现学了一下SCC-Tarjan,所谓Scc-tarjan,就是找到强连通分量并且缩点,特别好用,其原理就是利用dfs时间戳,每个点有自己的时间戳,同时再开一个记

ZOJ 3795 Grouping(Tarjan缩点+DAG)

Suppose there are N people in ZJU, whose ages are unknown. We have some messages about them. The i-th message shows that the age of person si is not smaller than the age of person ti. Now we need to divide all these N people into several groups. One'

ZOJ 3795 Grouping(强联通分量 + 缩点 + Dp)

Problem Description: Suppose there are N people in ZJU, whose ages are unknown. We have some messages about them. The i-th message shows that the age of person si is not smaller than the age of person ti. Now we need to divide all these N people into

ZOJ 3795 Grouping 强联通缩点+拓扑序+偏序集的最大链的大小

题意:有n个人,m个关系,关系是这两个人前一个人可以跟后一个比较. 那么问你我最少分多少组可以使这个组里的人都不可以比较. 只会强联通缩点,真特么不知道怎么做,想了一个小时,网上一看,还要会偏序集的东西,有一个叫Dilworth定理的东西. 定理1 令(X,≤)是一个有限偏序集,并令r是其最大链的大小.则X可以被划分成r个但不能再少的反链. 其对偶定理称为Dilworth定理: 定理2 令(X,≤)是一个有限偏序集,并令m是反链的最大的大小.则X可以被划分成m个但不能再少的链. 然后我们用到的是

ZOJ 3795:Grouping(缩点+最长路)

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5303 题意:有n个人m条边,每条边有一个u,v,代表u的年龄大于等于v,现在要将这n个人分成x个组,组内的人的年龄不能够直接或者间接比较,问最少可以分成多少组. 思路:一开始没看清题意,直接拓扑排序做了.后来听师兄说会有环,年龄大于等于,如果有环代表这里面的年龄相等,那么环里面的人都是每个人一组,缩完点之后那个点的长度就是点的人数,然后用DP最长路做. 1 #include

zoj 5303 Grouping 缩点求最长路

点击打开链接 Grouping Time Limit: 2 Seconds      Memory Limit: 65536 KB Suppose there are N people in ZJU, whose ages are unknown. We have some messages about them. The i-th message shows that the age of person si is not smaller than the age of person ti.

ZOJ Monthly, June 2014——Grouping

题目连接 题意: n个点,m条边 每条边两个整数a.b,表示a到b的有向边 求,至少需要几个集合,使得:每个集合中的元素互相不能到达 N(1≤ N≤ 100000), M(1≤ M≤ 300000) 分析: 相连的两个点不能在同一个集合中,那么,对于一个长度为n的链,至少需要n个集合:如果链中有环,相当于把环展开,这个就需要缩点处理 就是缩点之后求点权最长路 注意:模板中scc_cnt是从1开始的,如果使用缩点后的图,初始化时需要初始化总点数加一 因为总点数有限,用拓扑排序每次删除所有入度为零的

ZOJ Problem Set - 3795(缩点拓补)

题意:每条信息说明了两个一定不在一个集合里的人,求最少情况集合可以划分为多少子集. 一看就是拓补树的最高层数,但题意中隐含了可能有环(>=关系偏序),所以要先缩点,再拓补.当然,缩点之后图中没有环,直接dfs记忆化也是ok的. 代码: #include<iostream> #include<cstdio> #include<cmath> #include<map> #include<queue> #include<vector>

zoj Grouping(强连通+缩点+关键路径)

题意: 给你N个人,M条年龄大小的关系,现在打算把这些人分成不同的集合,使得每个集合的任意两个人之间的年龄是不可比的.问你最小的集合数是多少? 分析: 首先,假设有一个环,那么这个环中的任意两个点之间都是可比的,并且,和这个环相连的任意一个点或环也和这个环是可比的,因为关系具有传递性.但如果两个点或者环,无法处在同一条路径上,那么这两个点和环就是不可比的.所以,如果我们把这些环--强连通分量缩为一个点.强连通分量的点数就是缩点后的点权.那么缩点后的新图就是一个有向带权无环图,题目就是要求我们求出