题目
这一题对我有历史性的意义,因为我深刻意识到:
不要用namespace!
不要用namespace!
不要用namespace!
写此题解,以示他人。
(搞错重点了吧喂!)
好,回归正题:
这道题的思路是这样:
首先,用Kruskal算法。
(建议先把 并查集模板与 最小生成树模板 打了再继续看)
我们回顾一下Kruskal算法的过程:
把边按权值从小到大一条条排好,然后再从未选择的点中添加边,一直添加到节点数-1为止。
重点:为什么是节点数-1?因为最小生成树要让图连通。
可不可以不连通?
可以!
该题中,卫星电话的存在,就是为了可以让图断开。而最后求的最大边,就是最后一个添加到图中的边。
附上代码:
#include
#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.costsiz[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时的情况相等。