九度题目1446:Head of a Gang 2012年浙江大学计算机及软件工程研究生机试真题

本文介绍了一种使用并查集数据结构处理社交网络中群体形成与成员统计的问题。通过对电话号码进行转换和比较,实现了高效判断和合并不同的社交群体,并统计每个群体的人数及活跃时间。
AC 要注意最后输出的时候,可能有多个Gang,要按照字符串大小排序,小的在前
没有使用STL,AAA-ZZZ转换成010101-262626,并查集处理,效率不高
 
#include <iostream>
#include <cstdio>
#include <cstring>
#include<algorithm>
using namespace std;
typedef struct phone
{
    int time;
    int father;
}Phone;
typedef struct gang
{
    int peopleNum;
    int name;
}Gang;
Phone Town[262627];
Gang Index[1000];
void InitTown( )
{
    for(int i=10101; i<262627;i++)
    {
        Town[i].father = -1;
        Town[i].time = 0;
    }
}
void PrintGetNumber(int tmp)
{
    int n = 10000;
    while(tmp)
    {
        printf("%c",tmp/n+'A'-1);
        tmp %= n;
        n /= 100;
    }
}
int Getfather(int x)
{
    int tmp = x;
    while(Town[x].father!=-1)
    {
        x = Town[x].father;
    }
    int t = x;//保存这条路径上的根节点标号
    while(Town[tmp].father!=-1)
    {
        x = Town[tmp].father;//得到当前节点的双亲节点标号
        Town[tmp].father = t;//压缩集合路径,将这条路径上的所有点的双亲节点标记为根节点
        tmp = x;//访问路径上的下一个节点
    }
    return t;
}
int GetInt(char *tmp)
{
    int num = tmp[0]-'A'+1;
    for(int i =1 ; i<3; i++)
    {
        num *= 100;
        num += tmp[i]-'A'+1;    
    }
    return num;
}
int cmp(Gang a, Gang b)
{
    return a.name<b.name;
}
int main()
{
    int N,K,T,i;
    char a[3],b[3];
    while(cin>>N>>K)//K为标记
    {
        InitTown( );
        while(N--)
        {
            cin>>a>>b>>T;
            int ia = GetInt(a);
            int ib = GetInt(b);
            int fa = Getfather(ia);//得到a集合上的最终根节点
            Town[ia].time += T;//当a是a所在集合的根节点时,只加一次time
            int fb = Getfather(ib);//得到b集合上的最终根节点
            //ib和ia一定不相同
            Town[ib].time += T;
 
            if(fa != fb)         //a != b说明ab集合没有相交,将其相交
            {
                Town[fa].father = fb;
            }
        }
        int ans = 0;
        int h = 0;
        for(i =10101; i< 262627; i++)
        {
            if(Town[i].father == -1 && Town[i].time> 0)
            {
                int time = 0;
                int people = 0;
                int maxtime = -1;
                int maxpeople = i;
                for(int j = 10101; j<262627; j++)
                {
                    if(Getfather(j) == i)
                    {
                        people++;
                        time += Town[j].time;
                        if(maxtime < Town[j].time) 
                        {
                            maxtime = Town[j].time;
                            maxpeople = j;
                        }
                    }
                }
                if(people>2 && time > K*2)
                {
                        Index[h].peopleNum = people;
                        Index[h++].name = maxpeople;
                        ans++;
                }
            }
        }
        cout<<ans<<endl;
        sort(Index,Index+h,cmp);
        for(i=0;i<h;i++)
        {
            PrintGetNumber(Index[i].name);
            cout<<" "<<Index[i].peopleNum<<endl;
        }
    }
}
/**************************************************************
    Problem: 1446
    User: hrdjmax2
    Language: C++
    Result: Accepted
    Time:970 ms
    Memory:3584 kb
****************************************************************/
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值