n.boj 389 Shaking Your Cellphone(6th bupt acm problem D)

原创 2012年03月26日 17:47:29

Problem D. Shaking Your Cellphone

Description
Do you know a software called "WeiXin", a kind of chatting tool? There is an 
application called "Shaking for a while". Once you shake your cellphone, you 
can find those who shake their cellphone at same time. 
One day when Tom was shaking his cellphone, he thought about a problem: 
how large the friends group would be if everyone made friends once they 
find others who shake cellphone at same time and combine their friends 
group? 
We assume all the people are lonely and have no friends at the beginning. In 
other word, their friends group only contains themselves.
Input
First line contains an integer T (0 < T <= 10), indicate there are T cases. 
For each case, the first line contains an integer N (0 < N <= 1000), indicate 
the number of people who would shake their cellphone. 
Then follows N lines. Every line comes with an integer K[i] (0 <= K[i] <= 
1440), indicate the i-th person shakes cellphone K times a day. Then follows 
K[i] strings shown as "HH:MM", indicate the time the i-th person shakes 
cellphone.
Output
For each test case, the first line contains an integer X indicate how many 
friends group amount the people; the second line comes X integers in non-descending order, indicate the scale of each friends group.
Sample Input
3 00:00 00:01 00:02 
2 00:01 00:03 
1 00:03 
1 00:04
 
Sample Output
1 3
Source
thomas0726
 
 
 
 
今年校赛现场赛D题,简单说一下题意:
N个人摇手机,给出每个人摇手机的次数和相应的时刻点;在同一时刻摇手机的人们在一个好友圈内,而且对于息好友的好友,也是自己的好友,表示如果在好友圈A的人和好友圈B的另一人是好友的话,表示好友圈A和好友圈B实际是同一个好友圈,好友圈A和好友圈B里面的人都相互是好友。求最后独立的好友圈有多少人,每个圈子的规范(人数)有多少,按升序输出。
 
解题思路:抽象而言,将每个人看成一个点,如果互为好友,则两点相连;间接相连的两点也是直接相连的;相连的点属于一个集合,求集合数及其相应规模。
数据结构很重要;如果数据结构用邻接矩阵记录两点连通性的话,直观的想法就得用floyd求连通性,然后求相应的集合。但floyd的时间复杂度为O(n^3),即10^9了,会超时。应该用并查集结构,一个以时刻点做下标的并查集,一个以用户ID做下标的并查集。时间并查集记录第一个在这个时刻点摇号的用户ID,同时在用户并查集中设置它的父结点为它自身。如果用户摇手机的时刻先前已经记录有用户摇过,则当前用户的用户并查集的父结点为此时刻的时间并查集结点对应的用户ID在用户并查集中的根父结点。
为了提高合并速度,在找父结点的过程中,要做些优化
int get_fa(int i){
    if (fa[i] == i)
        return i;
    return fa[i] = get_fa(fa[i]); //将中间结点的父结点都设成根结点,提高后续合并速率
}
最后再做些排序工作即可。

 
#include<stdio.h>
#include<stdlib.h>
 
 
int fa[1010]; // 并查集,值为父亲结点 
int tt[1500]; // time table
int grp[1010];
int get_fa(int i){
    if (fa[i] == i)
        return i;
    return fa[i] = get_fa(fa[i]);
}
 
int get_date(char* t){
    int m = (t[0] - '0') * 10 + (t[1] - '0');
    int s = (t[3] - '0') * 10 + (t[4] - '0');
    return m * 60 + s;
}
 
int cmp(const void* a, const void* b){
    return *(int*)a - *(int*)b;
}
 
main(){
    int T;
    int N;
    char str[6];
 
    scanf("%d", &T);
    while (T--){
        int i, j;
        scanf("%d", &N);
        for (i = 0; i < N; i++){
            fa[i] = i;
            tt[i] = -1;
            grp[i] = 0;
        }
        for (i = N; i < 1500; i++){
            tt[i] = -1;
        }    
        for (i = 0; i < N; i++){
            int K;
            scanf("%d", &K);            
            while (K--){
                scanf("%s", str);
                int t_index = get_date(str);
                if (tt[t_index] == -1)
                    tt[t_index] = get_fa(i);            
                fa[get_fa(i)] = get_fa(tt[t_index]);
            }            
        }
        for (i = 0; i < N; i++)
            fa[i] = get_fa(i);
 
        qsort(fa, N, sizeof(int), cmp);
        int count = 0;
        int gn = 0; //group No. ; from 0
        int cg = fa[0];
        count ++;
        for (i = 1; i < N; i++){
            if (cg == fa[i])
                count ++;
            else {
                cg = fa[i];
                grp[gn] = count;
                count = 1;
                gn ++;            
            }            
        }
        grp[gn++] = count;
        qsort(grp, gn, sizeof(int), cmp);
        printf("%d\n", gn);
        for (i = 0; i < gn; i++){
            if (i == 0)
                printf("%d", grp[i]);
            else
                printf(" %d", grp[i]);
        }
        putchar('\n');
    }            
    return 0;
}


 

觉得自己还是不太熟悉并查集,因为一些细节问题调了好阵子。。

看了官方公布的参考答案(如下),不由感叹大牛对数据结构的操纵力……

#include<iostream>
#include<cstring>
#include<cmath>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<string>
#include<map>
#include<set>
#include<queue>
#include<cstdlib>
#include<ctime>
#include<stack>
using namespace std;
typedef long long llong;
const double EPS=1e-9;
const double Pi=acos(-1.0);
int Fa[2500],Cnt[2500];
int GetFa(int x)
{
    if (Fa[x]==x)
       return x;
    return Fa[x]=GetFa(Fa[x]);
}
void Merge(int x,int y)
{
     Fa[GetFa(x)]=Fa[GetFa(y)];
}
int GetDate(char s[])
{
    int x=(s[0]-'0')*10+s[1]-'0';
    int y=(s[3]-'0')*10+s[4]-'0';
    return x*60+y;
}
int main()
{
    //freopen("data.in","r",stdin);
    //freopen("data.out","w",stdout);
    int T,i,K,N;
    char st[10];
    scanf("%d",&T);
    while (T--)
    {
          for (i=0;i<2450;i++)
          {
              Fa[i]=i;
              Cnt[i]=0;
          }
          scanf("%d",&N);
          for (i=0;i<N;i++)
          {
              scanf("%d",&K);
              while (K--)
              {
                    scanf("%s",st);
                    Merge(i,GetDate(st)+1000);
              }
          }
          for (i=0;i<N;i++)
              Cnt[GetFa(i)]++;
          sort(Cnt,Cnt+2440);
          for (i=0;Cnt[i]==0;i++);
          printf("%d\n%d",2440-i,Cnt[i]);
          for (i++;i<2440;i++)
              printf(" %d",Cnt[i]);
          puts("");
    }
    system("pause");
    return 0;
}


 
版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

HDU/HDOJ 4043 BUPT 235 FXTZ II 2011ACM北京网络赛 D题

FXTZ II Accept:15     Submit:28 Time Limit:1000MS     Memory Limit:65536KB ...

The 37th ACM/ICPC Asia Regional JinHua Site Online Contest - D(爆搜)

来自ZZY的博客:http://blog.csdn.net/kk303/article/details/8008058   D - A very hard Aoshu problem      ...

The 37th ACM/ICPC Asia Regional JinHua Site Online Contest - D,F

D - A very hard Aoshu problem      数据范围很小呃... 暴力搜索即可...枚举等号的位置...再DFS得出左边的值..再DFS找右边有多少种方案可以等于左边的加法...
  • kk303
  • kk303
  • 2012-09-22 19:32
  • 2441

[刷题]ACM ICPC 2016北京赛站网络赛 D - Pick Your Players

DescriptionYou are the manager of a small soccer team. After seeing the shameless behavior of your t...

ACM_HDU 1032 The 3n + 1 problem

The 3n + 1 problem Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Other...

[ACM]The 3n + 1 problem

Problem Description Problems in Computer Science are often classified as belonging to a certain c...

ACM--次数最多--HDOJ 1032--The 3n + 1 problem--水(数据太弱)

HDOJ题目地址:传送门 The 3n + 1 problem Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: ...

ACM递归递推练习 Problem N

//假设柱子固定,有y片荷叶,可以通过y+1只青蛙;再固定柱子,可以通过前几个简单的例子推出每增加一个柱子,可以通过的青蛙数量增加一倍。由此可得出递归方程 #include using names...

杭电ACM HDU 1032 The 3n + 1 problem

The 3n + 1 problem Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Othe...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)