无线广播(Broadcast)【1】

无线广播(Broadcast) 

https://dsa.cs.tsinghua.edu.cn/oj/course.shtml?courseid=59

描述

某广播公司要在一个地区架设无线广播发射装置。该地区共有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

解法1: bfs(STL)

扫描二维码关注公众号,回复: 5399071 查看本文章
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
#include<algorithm>
#include<map>
using namespace std;
#define IMAX 10100
vector<int> t;
vector< vector<int> > g(IMAX,t);
int n,m;
queue<int> qu;
int main() {

    cin>>n>>m;
    g.resize(n+1);
    t.resize(n+1);
    for(int i=1; i<=m; i++)
    {
        int a,b;
        cin>>a>>b;
        g[b].push_back(a); // 必须双向
        g[a].push_back(b);
    }
    //bfs
    for(int j=1; j<=n; j++)
    {
        if(t[j]) continue;
        t[j]=1;
        qu.push(j);
        while(!qu.empty())
        {
            int cur=qu.front();
            qu.pop();
            for(int i=1; i<=g[cur].size(); i++)
            {
                if(t[g[cur][i]]==0)
                {
                    t[g[cur][i]]=0-t[cur];
                    qu.push(g[cur][i]);
                }
                else if(t[g[cur][i]]+t[cur]!=0)
                {
                    cout<<-1<<endl;
                    return 0;
                }
            }
        }
    }

    cout<<1<<endl;
    return 0;
}

解法2 (BSF)不使用STL

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define IMAX 10100
int t[IMAX]={
	0
};
int icount[IMAX]={
	0
};
int g[IMAX][IMAX/2];
int n,m;
int qu[IMAX*2];
int main() {
	
	cin>>n>>m;
	memset(icount,0,sizeof(icount));
	for(int i=1;i<=m;i++)
	{
		int a,b;
		cin>>a>>b;
		if(b<a) swap(a,b);
		g[a][++icount[a]]=b;
		g[b][++icount[b]]=a;
	}
	//bfs
	int index=-1,curindex=-1;
	for(int j=1;j<=n;j++)
	{
		if(t[j]) continue;
		t[j]=1;
		qu[(++index)%(IMAX)]=j;
		while(curindex!=index)
		{
			int cur=qu[++curindex];
			for(int i=1;i<=icount[cur];i++)
			{
			   //cout<<g[cur][i]<<"---"<<t[g[cur][i]]<<" "<<cur<<" "<<t[cur] <<endl;
			   if(t[g[cur][i]]==0)
			   {
	   			  t[g[cur][i]]=0-t[cur];
	   			  qu[(++index)%(IMAX)]=g[cur][i];
	   		   }
			   else if(t[g[cur][i]]+t[cur]!=0)
			   {
	   			  cout<<-1<<endl;
	   			  return 0;
			   }	
			}
		}
		index=-1,curindex=-1;
	}
	
   			  cout<<1<<endl;
   			  return 0;
}

解法3 并查集

#include<cstdio>
#include<iostream>
#include <string.h>
using namespace std;
int f[10002],d[10002],n,m;   //f保存祖先节点,d保存到其祖先节点的路径长。
int fa(int x)
{
    if (f[x]!=x)                       //查找时沿途更新祖先节点和路径长。
    {
        int last=f[x];                 //记录父节点(会在递归中被更新)。
        f[x]=fa(f[x]);                 //更新祖先节点。
        d[x]+=d[last];    //last 是原来的父亲 f[x] 就是根父亲
        //下面调整后,d[x]+=d[last] d[last]只有一次为原父亲 ;
        //更新路径长(原来连在父节点上)。
    }
    return f[x];
}
bool check(int a,int b)
{

    int x=fa(a),y=fa(b);

    if (x!=y) {
        f[x]=y;
        d[x]=d[b]+1-d[a];
    }//这样设置之后,会将x和y同步}

    else
    {
        if(abs(d[a]-d[b])%2==0)
        {
            cout<<-1<<endl;
            return false;
        };   //若已连接,则判断。
    }
    return true;
}
int main()
{
    int i,t;
    cin>>n>>m;
    memset(d,0,sizeof(d));
    for (i=1; i<=n; i++) f[i]=i;       //祖先节点初始化为自己,路径长为0。
    for(int i=1; i<=m; i++)
    {
        int a,b;
        cin>>a>>b;
        if(a>b) swap(a,b);
        if(!check(a,b))
            return 0;//检查当前两点是否已有边相连接。
    }
    cout<<1<<endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qiang_____0712/article/details/87923838