描述
某广播公司要在一个地区架设无线广播发射装置。该地区共有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;
}
提交结果: