一道做起来很舒服的题

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个关系(a b),代表a会和b比较,且关系可以传递,问这么把这些人分到不同的群组里面,使得每个群组里面的人都不能比较,差不多是这个意思了。


第一感觉是强联通,得到一个有向无环图,找到最大的强联通分量,然后想想不太对,如果一个链够长,好像也可以,然后改了改,改成缩点之后,跑最长链,其中强联通分量的节点个数是该节点的权重,用个记忆话搜索,从重建的图中入度为0的点开始搜,找个最大值。


#include <stdio.h>
#include <string.h>
#include <algorithm>

using namespace std;

const int maxm = 300010;
const int maxn = 100010;

typedef struct Edge {
    int to,next;
};

Edge edge[maxm];
int head[maxn],cnt;
int stack[maxn],instack[maxn],dfn[maxn],low[maxn],col[maxn];
int sec,top,ttime;
int ans_max,ans_len;
int deg[maxn],sum[maxn];

Edge redge[maxm];
int rhead[maxn],rcnt;
int mark[maxn];

int queue[maxn];

void Add(int from,int to) {
    edge[cnt].to = to;
    edge[cnt].next = head[from];
    head[from] = cnt ++;
}

void rAdd(int from,int to) {
    redge[rcnt].to = to;
    redge[rcnt].next = rhead[from];
    rhead[from] = rcnt ++;
}

void Tarjan(int s) {
    stack[top ++] = s;
    instack[s] = 1;
    dfn[s] = low[s] = ttime ++;
    for(int i = head[s]; i + 1; i = edge[i].next) {
        int to = edge[i].to;
        if(dfn[to] == -1) {
            Tarjan(to);
            low[s] = min(low[s],low[to]);
        }
        else if(instack[to]) {
            low[s] = min(low[s],dfn[to]);
        }
    }
    if(low[s] == dfn[s]) {
        int x;
        int t = 0;
        do {
            x = stack[-- top];
            instack[x] = 0;
            col[x] = sec;
            t ++;
            //printf("%d\n",x);
        }while(s != x);
        //printf("*****\n");
        sum[sec] = t;
        sec ++;
        ans_max = max(ans_max,t);
    }
}

void rebuild(int N) {
    memset(rhead,-1,sizeof(rhead));
    rcnt = 0;
    for(int i = 1; i <= N; i ++) {
        int from = i;
        for(int j = head[i]; j + 1; j = edge[j].next) {
            int to = edge[j].to;
            if(col[from] != col[to]) {
                rAdd(col[from],col[to]);
                //printf("%d -> %d\n",col[from],col[to]);
            }
        }
    }
}

int dfs(int s) {
    int ans = 0;
    //printf("s = %d\n",s);
    for(int i = rhead[s]; i + 1; i = redge[i].next) {
        int to = redge[i].to;
        if(mark[to]) {
            ans = max(ans,mark[to]);
            continue;
        }
        dfs(to);
        ans = max(ans,mark[to]);
    }
    mark[s] = ans + sum[s];
    return mark[s];
}

int main() {
    int N,M;
    while(~scanf("%d%d",&N,&M)) {
        memset(head,-1,sizeof(head));
        memset(dfn,-1,sizeof(dfn));
        memset(instack,0,sizeof(instack));
        memset(sum,0,sizeof(sum));
        top = cnt = sec = ttime = 0;
        for(int i = 0; i < M; i ++) {
            int a,b;
            scanf("%d%d",&a,&b);
            Add(a,b);
        }
        ans_max = 0;
        for(int i = 1; i <= N; i ++) {
            if(dfn[i] == -1) {
                Tarjan(i);
            }
        }
        //printf("ans_max = %d\n",ans_max);
        //printf("sec = %d\n",sec);
        rebuild(N);
        memset(deg,0,sizeof(deg));
        for(int i = 0; i < sec; i ++) {
            for(int j = rhead[i]; j + 1; j = redge[j].next) {
                int to = redge[j].to;
                deg[to] ++;
            }
        }
        ans_len = 0;
        for(int i = 0; i < sec; i ++) {
            if(deg[i] == 0) {
                memset(mark,0,sizeof(mark));
                int x = dfs(i);
                ans_len = max(x,ans_len);
            }
        }
        //printf("len = %d\n",ans_len);
        printf("%d\n",max(ans_len,ans_max));
    }
    return 0;
}

做起来很舒服,没有什么难点,把简单的东西组合起来的题。
内容概要:本文详细探讨了基于阻尼连续可调减振器(CDC)的半主动悬架系统的控制策略。首先建立了CDC减振器的动力学模型,验证了其阻尼特性,并通过实验确认了模型的准确性。接着,搭建了1/4车辆悬架模型,分析了不同阻尼系数对悬架性能的影响。随后,引入了PID、自适应模糊PID和模糊-PID并联三种控制策略,通过仿真比较它们的性能提升效果。研究表明,模糊-PID并联控制能最优地提升悬架综合性能,在平顺性和稳定性间取得最佳平衡。此外,还深入分析了CDC减振器的特性,优化了控制策略,并进行了系统级验证。 适用人群:从事汽车工程、机械工程及相关领域的研究人员和技术人员,尤其是对车辆悬架系统和控制策略感兴趣的读者。 使用场景及目标:①适用于研究和开发基于CDC减振器的半主动悬架系统的工程师;②帮助理解不同控制策略(如PID、模糊PID、模糊-PID并联)在悬架系统中的应用及其性能差异;③为优化车辆行驶舒适性和稳定性提供理论依据和技术支持。 其他说明:本文不仅提供了详细的数学模型和仿真代码,还通过实验数据验证了模型的准确性。对于希望深入了解CDC减振器工作原理及其控制策略的读者来说,本文是一份极具价值的参考资料。同时,文中还介绍了多种控制策略的具体实现方法及其优缺点,为后续的研究和实际应用提供了有益的借鉴。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值