Codeforces Round #151 (Div. 2)

D题:

这题比较的坑,首先题意要明确:

有一些点,给你这些点的颜色(可能重复),再给你这些点构成的图,叫你求 某种颜色 周围 不同的颜色数,输出其中数目最多的那个颜色,也就是这个颜色周围不同的颜色数最多,如果数目相同,输出颜色序号小的那个。

这里有个大坑,题目要求是求 某种颜色 周围,而不是某个点周围,因为有些点的颜色可能相同, 也就是说在求某种颜色周围的时候可能是 多个点的 周围一起求。

当然这种方法比较笨。我们可以把题目给的 节点图 转化为 颜色图 ,对颜色图来说,我们只需要存每一条边的起点终点就行了,然后按起点排序, 把起点相同的边放在一起处理。

这里又有个小trick,在存边的时候,我们还要把 自己 到 自己 的所有边加进去,因为会出现这样的数据

3 1

13 13 1

1 2

如果不加自己的边,那么答案是13,,实际上答案是1.

直接上代码:


#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <map>
#include <vector>
#include <set>
#include <stack>
#include <queue>
using namespace std;
#define N 310000
#define Dbag printf("haha\n");
#define lson (pos<<1)
#define rson (pos<<1|1)
#define LL long long

struct node
{
    int a,b;
}e[N];
int c[N];
int cmp(node a, node b)
{
    return a.a < b.a;
}
int main()
{
    int n,m;
    int cnt = 0;
    while(~scanf("%d%d", &n, &m))
    {
        for(int i = 1; i <= n; i++)
            scanf("%d",&c[i]);
        for(int i = 0; i < m; i++)         //节点图转换为颜色图
        {
            int a,b;
            scanf("%d%d",&a, &b);
            e[cnt].a = c[a]; e[cnt++].b = c[b];
            e[cnt].a = c[b]; e[cnt++].b = c[a];
        }
        for(int i = 1; i <= n; i++){e[cnt].a = c[i]; e[cnt++].b = c[i];} //把自己加进去
        sort(e, e+cnt, cmp); //排序
        int num = 0, ans=-1;
        set <int> S;
        S.insert(e[0].a);
        for(int i = 0; i < cnt; i++)
        {
            if((i!=0&&e[i].a!=e[i-1].a)||i==cnt-1)
            {
                if(num<=S.size())
                {
                    if(num==S.size())
                    {
                        if(ans>e[i-1].a&&ans!=-1)
                            ans = e[i-1].a;
                        if(ans==-1)
                            ans = e[i-1].a;
                    }
                    else
                    {
                        num=S.size();
                        ans=e[i-1].a;
                    }
                }
                S.clear();
                S.insert(e[i].a);
            }
            S.insert(e[i].b);
        }
        printf("%d\n",ans);
    }

    return 0;
}





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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值