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. 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}


Author: LUO, Jiewei

Source: ZOJ Monthly, June 2014

m条a年龄大于b年龄的信息,最少需要多少组,能够使得每组里面的年龄无法比较。

缩点之后求最长路径。

#include<stdio.h>
#include<string.h>
#include<queue>
#include<algorithm>
#define M 100007
using namespace std;
using namespace std;
int head[M],low[M],dfn[M];
int stack[M],vis[M],belong[M];
int head1[M],dis[M],val[M];
int cnt,scnt,begin,num,num1;
int n,m;
struct E
{
    int to,next;
}edge[M*3],edge1[M*3];

void addedge(int u,int v)
{
    edge[num].to=v;
    edge[num].next=head[u];
    head[u]=num++;
}

void addedge1(int u,int v)
{
    edge1[num1].to=v;
    edge1[num1].next=head1[u];
    head1[u]=num1++;
}

void init()
{
    cnt=scnt=begin=num=num1=0;
    memset(head,-1,sizeof(head));
    memset(head1,-1,sizeof(head1));
    memset(dfn,0,sizeof(dfn));
    memset(vis,0,sizeof(vis));
    memset(low,0,sizeof(low));
    memset(val,0,sizeof(val));
}

void tarjan(int x)
{
    int v;
    dfn[x]=low[x]=++cnt;
    stack[++begin]=x;
    for(int i=head[x];i!=-1;i=edge[i].next)
    {
        v=edge[i].to;
        if(!dfn[v])
        {
            tarjan(v);
            low[x]=min(low[x],low[v]);
        }
        else if(!vis[v])
            low[x]=min(low[x],dfn[v]);
    }
    if(low[x]==dfn[x])
    {
        scnt++;
        do
        {
            v=stack[begin--];
            belong[v]=scnt;
            val[scnt]++;
            vis[v]=1;
        }while(v!=x);
    }
}

void cal(int x)
{
    if(dis[x]!=-1)return;
    dis[x]=val[x];
    int now=val[x];
    for(int j=head1[x];j!=-1;j=edge1[j].next)
    {
        int v=edge1[j].to;
        cal(v);
        dis[x]=max(dis[x],dis[v]+now);
    }
}

void solve()
{
     for(int i=1;i<=n;i++)
            if(!dfn[i])tarjan(i);
    for(int u=1;u<=n;u++)
        for(int i=head[u];i!=-1;i=edge[i].next)
        {
            int v=edge[i].to;
            if(u!=v&&belong[u]!=belong[v])
                addedge1(belong[u],belong[v]);
        }
    for(int i=1;i<=scnt;i++)
        dis[i]=-1;
    for(int i=1;i<=scnt;i++)
        cal(i);
    int ans=0;
    for(int i=1;i<=scnt;i++)
        ans=max(ans,dis[i]);
    printf("%d\n",ans);
}

int main()
{
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        init();
        int u,v;
        for(int i=0;i<m;i++)
        {
            scanf("%d%d",&u,&v);
            addedge(u,v);
        }
        solve();
    }
    return 0;
}
时间: 2024-10-06 20:35:40

zoj 5303 Grouping 缩点求最长路的相关文章

zoj3795 Grouping --- 强连通,求最长路

给定图,求把至少把图拆成几个集合能够使集合内的点没有直接或间接关系. 首先由题意可得图中可能含环,而环里面的点肯定是要拆开的. 缩点建图得DAG图,可以想象一下..把图从入度为零的点向下展开,位于同一层的点放在一个集合是没有关系的, 那么题目所求的问题就转化成求图中最长路的问题了. 这个题的实质和 这题 其实是一模一样的.. #include <iostream> #include <cstring> #include <string> #include <cst

zoj-3795-Grouping-tarjan缩点求最长路

用tarjan进行缩点. 然后用dfs求最长路.水体... #include<stdio.h> #include<string.h> #include<algorithm> #include<iostream> #include<vector> #include<map> #include<stack> using namespace std; #define maxn 110000 vector<int>ol

poj 3592 Instantaneous Transference 强连通图 缩点 再求最长路

1 #include<iostream> 2 #include<stdio.h> 3 #include<string.h> 4 #include<stack> 5 #include<queue> 6 using namespace std; 7 #define maxx 44 8 #define maxx2 44*44 9 #define INF 99999999 10 char s[maxx][maxx]; 11 bool tong[maxx2

POJ 3592--Instantaneous Transference【SCC缩点新建图 &amp;amp;&amp;amp; SPFA求最长路 &amp;amp;&amp;amp; 经典】

Instantaneous Transference Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 6177   Accepted: 1383 Description It was long ago when we played the game Red Alert. There is a magic function for the game objects which is called instantaneous

POJ 3592--Instantaneous Transference【SCC缩点新建图 &amp;&amp; SPFA求最长路 &amp;&amp; 经典】

Instantaneous Transference Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 6177   Accepted: 1383 Description It was long ago when we played the game Red Alert. There is a magic function for the game objects which is called instantaneous

HDU - 6201 transaction transaction transaction(spfa求最长路)

题意:有n个点,n-1条边的无向图,已知每个点书的售价,以及在边上行走的路费,问任选两个点作为起点和终点,能获得的最大利益是多少. 分析: 1.从某个结点出发,首先需要在该结点a花费price[a]买书,然后再在边上行走,到达目的地后,在目的地b获得price[b]. 2.因此可以建立两个虚拟结点, 虚拟结点1连向n个点,边权分别为-price[i],表示以i为起点,需花费price[i]买书. n个点连向虚拟结点2,边权分别为price[i],表示以i为终点,通过卖书可得price[i]. 3

【HDOJ1217】【Floyd求最长路】

http://acm.hdu.edu.cn/showproblem.php?pid=1217 Arbitrage Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 9455    Accepted Submission(s): 4359 Problem Description Arbitrage is the use of discrepa

UVA 11324 The Largest Clique (强连通缩点 + DAG最长路)

链接 : http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=30726 题意 : 有向图G,求一个最大的点集,使得点集中任意两个节点u和v,满足 要么u可以到达v,要么v可以到达u,或者u和v可以相互到达. 可以强连通缩点成一张DAG,以为每个强连通分量要么选要么不选.求DAG上的最长路 二次建图 用了2种不同的方法,也分别用了记忆花搜索DP和直接递推DP vector建图和记忆化搜索: #include <algorithm

HDU 2196 Computer(树形DP求最长路)

Problem Description A school bought the first computer some time ago(so this computer's id is 1). During the recent years the school bought N-1 new computers. Each new computer was connected to one of settled earlier. Managers of school are anxious a