清华OJ——无线广播

描述

某广播公司要在一个地区架设无线广播发射装置。该地区共有n个小镇,每个小镇都要安装一台发射机并播放各自的节目。

不过,该公司只获得了FM104.2和FM98.6两个波段的授权,而使用同一波段的发射机会互相干扰。已知每台发射机的信号覆盖范围是以它为圆心,20km为半径的圆形区域,因此,如果距离小于20km的两个小镇使用同样的波段,那么它们就会由于波段干扰而无法正常收听节目。现在给出这些距离小于20km的小镇列表,试判断该公司能否使得整个地区的居民正常听到广播节目。

输入

第一行为两个整数n,m,分别为小镇的个数以及接下来小于20km的小镇对的数目。 接下来的m行,每行2个整数,表示两个小镇的距离小于20km(编号从1开始)。

输出

如果能够满足要求,输出1,否则输出-1。

输入样例

4 3
1 2
1 3
2 4

输出样例

1

限制

1 ≤ n ≤ 10000

1 ≤ m ≤ 30000

不需要考虑给定的20km小镇列表的空间特性,比如是否满足三角不等式,是否利用传递性可以推出更多的信息等等。

时间:2 sec

空间:256MB

提示

BFS

思路:

1、每个小镇为一个顶点,每个20km内的关系为两个顶点的一条边,显然本题为无向边。使用邻接表存储图结构。

2、每个结点的初始波段赋值为-1,借助队列从任意顶点开始做图的BFS。每次取出队头元素t,检查其波段值fm[t],如果为-1,表示其未设置波段,可以为先其分配一个波段(为方便处理,这里用1表示,即fm[t] = 1)。遍历其所有邻接点j,如果邻接点波段值为-1,为邻接点赋值 fm[j] = fm[t] ^ 1,表示邻接点必须使用另外一个波段。如果不为-1,考察是否与t相等,如果相等,表示冲突,返回false,如果不等,说明此结点分配正确,算法继续执行。

3、直到所有结点遍历完成没有返回false,则返回ture

算法最坏情况下需遍历所有顶点,每个顶点遍历其所有临边,时间复杂度O(n + e),代码如下:

#include<cstdio>
#include<cstring>
using namespace std;
const int N = 10005, M = 3e4 + 5;
int h[N], e[M * 2], ne[M * 2], idx;
int fm[N], n, m;
int q[N];

void add(int a, int b){
    e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}

bool check(){
    int hh = 0, tt = -1;
    q[++tt] = 1;         //这里实际上测试用例中不一定包含结点1,严格来说,应该取必定存在的结点,即在输入时任意获取一个a或b,先入队。但用1,能AC
    while(hh <= tt){
        int t = q[hh++];
        if(fm[t] == -1) fm[t] = 1;

        for(int i = h[t]; i != -1; i = ne[i]){
            int j = e[i];
            if(fm[j] == -1) {
                fm[j] = fm[t] ^ 1;
                q[++tt] = j;
            }
            else if(fm[j] == fm[t]) return false;
        }

    }
    return true;
}

int main(){
    scanf("%d%d", &n, &m);
    memset(h, -1, sizeof(h));
    memset(fm, -1, sizeof(fm));
    while(m --){
        int a, b;
        scanf("%d%d", &a, &b);
        add(a, b), add(b, a);
    }
    if(check()) puts("1");
    else puts("-1");

    return 0;
}

提交结果:

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值