• 题解 P1991 【无线通讯网】


    题目

    这一题对我有历史性的意义,因为我深刻意识到:

    不要用namespace!

    不要用namespace!

    不要用namespace!

    写此题解,以示他人。

    (搞错重点了吧喂!)


    好,回归正题:

    这道题的思路是这样:

    首先,用Kruskal算法。

    (建议先把 并查集模板与 最小生成树模板 打了再继续看)

    我们回顾一下Kruskal算法的过程:

    把边按权值从小到大一条条排好,然后再从未选择的点中添加边,一直添加到节点数-1为止。

    重点:为什么是节点数-1?因为最小生成树要让图连通。

    可不可以不连通?

    可以!

    该题中,卫星电话的存在,就是为了可以让图断开。而最后求的最大边,就是最后一个添加到图中的边。

    附上代码:

    #include <bits/stdc++.h>
    #define MAXN 200005
    int node,edgenum=0,ans=0,k=0,s;
    int fat[MAXN],siz[MAXN];
    //坐标 
    struct pair
    {
    	int first,second;
    }	a[MAXN];
    //图 
    struct EDGE
    {
    	int from,to;double cost;
    }	e[MAXN];
    //比较器 
    bool cmp(EDGE a,EDGE b)	{return a.cost<b.cost;}
    //并查集 + 路径压缩 + 启发式搜索 
    int Find(int x){ return (fat[x]==x)? x : fat[x]=Find(fat[x]); }
    void unionn(int x,int y){
    	x=Find(x); y=Find(y);
    	if(siz[x]>siz[y])	std::swap(x,y);
    	fat[x]=y;	siz[y]+=siz[x]; 
    }
    //两点之间距离公式 
    double distance(pair m , pair n)
    {
    	double ans=std::sqrt( (m.first-n.first)*(m.first-n.first) + (m.second-n.second)*(m.second-n.second) );
    	return ans;
    }
    
    int main()
    {
    	double d;
    	std::scanf("%d%d",&s,&node);
    	for(int i=1;i<=node;++i)	scanf("%d%d",&a[i].first,&a[i].second);
    	for(int i=1;i<=node;++i)	{fat[i]=i;	siz[i]=1;}	//初始化 
    	for(int i=1;i<=node;++i)	//构图 
    	{
    		for(int j=i+1;j<=node;++j)
    		{
    			e[ ++edgenum ].from=i;	e[ edgenum ].to=j;
    			e[ edgenum ].cost=distance(a[i],a[j]);
    		}
    	}
    	//	Kurskal 
    	std::sort(e+1,e+edgenum+1,cmp);
    	for(int i=1;i<=edgenum;++i)
    	{
    		if(k==node-s) break;//节点数-卫星电话数
    		if(Find(e[i].from) != Find(e[i].to))
    		{
    			unionn(e[i].from,e[i].to); 
    			d=e[i].cost;	++k; 
    		}
    	}		
    	std::printf("%.2lf",d);
    	return 0;
    }
    

    其实这题的数据有点弱。

    我的代码是有缺陷的,可是AC了。

    应该还要再添加一些特判。

    比如,当卫星电话数大于节点数时,d应该为0。

    当卫星电话数为0时,应该与卫星电话为1时的情况相等。

  • 相关阅读:
    MySQL/MariaDB 版本选择
    Linux查看某个进程的磁盘IO读写情况 pidstat
    Oracle 11gR2 Database UNDO表空间使用率居高不下处理
    Linux十字病毒查杀处理
    MySQL字符集与校对
    点与线、线与线之间的位置关系
    [向量] 点积应用-两个向量夹角
    点与线的距离及垂足点
    unity 4.6.1脚本解析出错,没有激活的勾,方法顺序出错
    Error building Player: Exception: Could not start java
  • 原文地址:https://www.cnblogs.com/cyl-oi-miracle/p/13383087.html
Copyright © 2020-2023  润新知