zoukankan      html  css  js  c++  java
  • hihocoder 微软编程之美2015 初赛 第一场 (树算法 + 暴力思想 + 搜索思想)

    题目1 : 彩色的树

    时间限制:2000ms
    单点时限:1000ms
    内存限制:256MB

    描述

    给定一棵n个节点的树,节点编号为1, 2, …, n。树中有n - 1条边,任意两个节点间恰好有一条路径。这是一棵彩色的树,每个节点恰好可以染一种颜色。初始时,所有节点的颜色都为0。现在需要实现两种操作:

    1. 改变节点x的颜色为y;

    2. 询问整棵树被划分成了多少棵颜色相同的子树。即每棵子树内的节点颜色都相同,而相邻子树的颜色不同。

    输入

    第一行一个整数T,表示数据组数,以下是T组数据。

    每组数据第一行是n,表示树的节点个数。接下来n - 1行每行两个数i和j,表示节点i和j间有一条边。接下来是一个数q,表示操作数。之后q行,每行表示以下两种操作之一:

    1. 若为"1",则询问划分的子树个数。

    2. 若为"2 x y",则将节点x的颜色改为y。

    输出

    每组数据的第一行为"Case #X:",X为测试数据编号,从1开始。

    接下来的每一行,对于每一个询问,输出一个整数,为划分成的子树个数。

    数据范围

    1 ≤ T ≤ 20

    0 ≤ y ≤ 100000

    小数据

    1 ≤ n, q ≤ 5000

    大数据

    1 ≤ n, q ≤ 100000

    样例输入
    2
    3
    1 2
    2 3
    3
    1
    2 2 1
    1
    5
    1 2
    2 3
    2 4
    2 5
    4
    1
    2 2 1
    2 3 2
    1
    
    样例输出
    Case #1:
    1
    3
    Case #2:
    1
    5
    

    分析:主要题意就是输出一棵树中连通分量的个数,但此题目里的连通分量和平时的连通分量不太一样,就是每个连通分量内的
    节点的颜色必须是一样的,否则就要划分到不同的连通分量上。常规的思路,每次在修改完某些节点后,但我们想去计算这棵树
    中有多少子树(即连通分量),完全可以用dfs搜索,但是这道题目中如果询问次数很多,必然超时!
    所以需要修改思路。
    假设我们当前修改节点x的颜色,将其颜色修改为y。
    在我们修改后,其对应的颜色可能会发生改变,也可能不会。子树的数目可能增加,也可能减少,还有可能不变。
    回到节点x,我们修改节点x的颜色后,我们访问所有与x节点有直接相邻关系的节点xx

    假设:原来x的颜色为ori, 修改后的颜色为cur,将会产生下面四种情况:( f[]数组保存所有节点的颜色信息 )
    ans:表示x节点颜色修改前的子树的个数:接下来计算x节点颜色的修改对子树数目的影响
    ori==f[xx] && cur==f[xx]
    ans不变
    ori==f[xx] && cur!=f[xx] ans++;
    ori!=f[xx] && cur==f[xx] ans--;
    ori!=f[xx] && cur!=f[xx]
    ans不变

    代码:(本以为此算法同样可以过大数据,但还是TLE了)
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <ctype.h>
    #include <math.h>
    #include <algorithm>
    #define N 5010
    
    
    using namespace std;
    
    int map[N][N];
    int fa[N];
    bool vis[N];
    int n, q;
    
    int main()
    {
        int t;
        scanf("%d", &t);
        int i, j, k;
        int cnt=1;
    
        while(t--)
        {
            scanf("%d", &n);
            memset(fa, 0, sizeof(fa));
            memset(map, 0, sizeof(map));
    
            int u, v;
            for(i=0; i<n-1; i++)
            {
                scanf("%d %d", &u, &v);
                map[u][v]=1;
                map[v][u]=1;
            }
    
    
            scanf("%d", &q);
            printf("Case #%d:
    ", cnt++ );
            int ans=1;
            while(q--)
            {
                int dd;
                int x, y;
                scanf("%d", &dd);
                if(dd==1)
                {
                    printf("%d
    ", ans );
                }
                else
                {
                    scanf("%d %d", &x, &y);
                    int ori=fa[x];
                    fa[x]=y;
                    int cur=y;
                    for(i=1; i<=n; i++)
                    {
                        if(map[x][i]==1 && i!=x )
                        {
                            if(ori==fa[i] && cur!=fa[i] )
                            {
                                ans++;
                            }
                            else if(ori!=fa[i] && cur!=fa[i])
                            {
                                ans=ans+0;
                            }
                            else if(ori==fa[i] && cur==fa[i])
                            {
                                ans+=0;
                            }
                            else if(ori!=fa[i] && cur==fa[i])
                            {
                                ans--;
                            }
                        }
                    }
                }
            }
        }
        return 0;
    }
    

    题目3 : 质数相关

    时间限制:2000ms
    单点时限:1000ms
    内存限制:256MB

    描述

    两个数a和 b (a<b)被称为质数相关,是指a × p = b,这里p是一个质数。一个集合S被称为质数相关,是指S中存在两个质数相关的数,否则称S为质数无关。如{2, 8, 17}质数无关,但{2, 8, 16}, {3, 6}质数相关。现在给定一个集合S,问S的所有质数无关子集中,最大的子集的大小。

    输入

    第一行为一个数T,为数据组数。之后每组数据包含两行。

    第一行为N,为集合S的大小。第二行为N个整数,表示集合内的数。

    输出

    对于每组数据输出一行,形如"Case #X: Y"。X为数据编号,从1开始,Y为最大的子集的大小。

    数据范围

    1 ≤ T ≤ 20

    集合S内的数两两不同且范围在1到500000之间。

    小数据

    1 ≤ N ≤ 15

    大数据

    1 ≤ N ≤ 1000

    样例输入
    3
    5
    2 4 8 16 32
    5
    2 3 4 6 9
    3
    1 2 3
    
    样例输出
    Case #1: 3
    Case #2: 3
    Case #3: 2
    
    此题目:小数据的情况下,直接暴力就可以了,大数据的算法没想出来!
    代码:
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <ctype.h>
    #include <math.h>
    #include <vector>
    #include <algorithm>
    #define N 100000+10
    
    
    using namespace std;
    int f[500002];
    void sushu()
    {
        memset(f, 0, sizeof(f));
        int i=2;
        f[1]=1;
        f[0]=1;
        int dd=sqrt(500000+0.5);
        while(i<=dd)
        {
            for(int j=i*2; j<=500000; j+=i)
            {
                f[j]=1;
            }
            i++;
            while(f[i]==1)
                i++;
        }
    }
    
    int a[1010];
    int b[1010], e=0;
    
    int main()
    {
        int t;
        scanf("%d", &t);
        sushu();
        int n;
        int i, j, k;
    
        int dd=1;
        while(t--)
        {
            scanf("%d", &n);
            for(i=0; i<n; i++)
            {
                scanf("%d", &a[i]);
            }
            int len=0;
            bool flag;
            int cnt;
            for(i=0; i<n; i++)
            {
    
                memset(b, 0, sizeof(b));
                e=0;
                b[e++]=a[i];
                for(j=i+1; j<n; j++)
                {
                    flag=true;
                    for(k=0; k<e; k++)
                    {
                        if(a[j]%b[k]==0 && f[a[j]/b[k]]==0 )
                        {
                            flag=false;
                            break;
                        }
                    }
                    if(flag==true)
                        b[e++]=a[j];
                }
                if(e > len )
                    len = e;
            }
            printf("Case #%d: %d
    ", dd++, len );
        }
        return 0;
    }
    
    
    
    
    
  • 相关阅读:
    UIAutomator简介
    初识Anrdiod SDK
    Andriod App类型简介
    Mybatis之collection嵌套查询mapper文件写法
    Ubuntu16.04 启动纯文本界面方法
    Ubuntu16.04网络不能访问解决办法
    JavaScript之简易http接口测试工具网页版
    SpringBoot之修改单个文件后立刻生效
    JavaScript之Json的使用
    Ajax之Jquery封装使用举例2(Json和JsonArray处理)
  • 原文地址:https://www.cnblogs.com/yspworld/p/4456153.html
Copyright © 2011-2022 走看看