cogs 1298. 通讯问题 Tarjan

1298. 通讯问题

★★   输入文件:jdltt.in   输出文件:jdltt.out   简单对比
时间限制:1 s   内存限制:128 MB

【题目描述】

一个篮球队有n个篮球队员,每个队员都有联系方式(如电话、电子邮件等)。但并不是每个队员的联系方式都公开,每个队员的联系方式只有一部分队员知道。问队员可以分成多少个小组,小组成员之间可以相互通知(包括一个队员一个组,表示自己通知自己)。

【输入格式】

输入文件有若干行

第一行,一个整数n,表示共有n个队员(2<=n<=100)

下面有若干行,每行2个数a、b,a、b是队员编号,表示a知道b的通讯方式。

【输出格式】

输出文件有若干行

第一行,1个整数m,表示可以分m个小组,下面有m行,每行有若干个整数,表示该小组成员编号,输出顺序按编号由小到大。

【样例输入】

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

【样例输出】

8

1 2 3

4 6

5

7 8

9

10

11

12

 

我太弱了 只会刷水题

这一道题比较坑就是要按照顺序输出 不止是说每一组都要排序(其实也不用排序 从1-n按顺序遍历就行 具体看代码)

针对组与组之间也要排序(其实就是按照每一组的第一个数字的大小排序,这一道题特别水 数据范围特小 写一个n^2选择排序暴力一下就过了QAQ)

 

代码:

#include<vector>
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<string>
#include<cstring>
#define maxn 105
using namespace std;
vector<int> v[maxn];
int size[maxn],dfn[maxn],low[maxn],belong[maxn],st[maxn],tim,scc_cnt,cnt;
bool bein[maxn];
vector<int> ans[maxn];
void Tarjan(int rt){
    dfn[rt]=low[rt]=++tim;
    st[++cnt]=rt;
    bein[rt]=true;
    for(int i=0;i<v[rt].size();i++)
    {
        int to=v[rt][i];
        if(!dfn[to])
            Tarjan(to),low[rt]=min(low[rt],low[to]);
        else if(bein[to])
            low[rt]=min(low[rt],dfn[to]);
    }
    if(dfn[rt]==low[rt])
    {
        scc_cnt++;
        int k;
        do {
            k=st[cnt];
            cnt--;
            bein[k]=false;
            size[scc_cnt]++;
            belong[k]=scc_cnt;
        }while(k^rt);
    }
}
int main()
{
    freopen("jdltt.in","r",stdin);
    freopen("jdltt.out","w",stdout);
    int n,x,y;scanf("%d",&n);
    while(scanf("%d%d",&x,&y)!=EOF)//读入若干行 
    {
        v[x].push_back(y);//这是单向边啊 
    }
    for(int i=1;i<=n;i++)
        if(!dfn[i])
            Tarjan(i);
    printf("%d\n",scc_cnt);
    for(int i=1;i<=scc_cnt;i++)
    {
        for(int j=1;j<=n;j++)
        {
            if(belong[j]==i)
                ans[i].push_back(j);
                //printf("%d ",j);
        }
        //printf("\n");
    }
    for(int i=1;i<=scc_cnt;i++)//常数小 随便乱搞
        for(int j=i+1;j<=scc_cnt;j++)
            if(ans[i][0]>ans[j][0])
                swap(ans[i],ans[j]);
    for(int i=1;i<=scc_cnt;i++)
    {
        for(int j=0;j<ans[i].size();j++)
            printf("%d ",ans[i][j]);
        printf("\n");
    }
    return 0;
}

 

转载于:https://www.cnblogs.com/Tidoblogs/p/11329712.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值