原因:为了练习一下Kruskal,随便到poj找了一个求mst的题。- -
题意:给一堆城市的坐标点,任何两个城市之间有两种通讯方式,一种是直接卫星通讯,不管两个城市距离多远,都可以通讯,另一种是微波通讯,通讯距离不超过D,D越大成本越高,给出s个城市之间可以用卫星通讯,其他必须得用微波,求所有城市都可以互相通讯的最小成本。
分析:先用Kruskal求出mst,记录mst中的所有边,那么删除了最大的那s-1条边后最大的边就是答案,如果没有边了返回0,不过貌似这题不会所有城市之间都用卫星通讯。还有一个坑爹的地方就是输出时候的占位符必须是%0.2f,这个不能理解。。看了discuss改了才AC。
其他做法:直接二分答案然后验证。。
代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
#include <cmath>
#include <queue>
using namespace std;
typedef pair<int,int> P;
struct edge{ //无向边
int u,v;
double dis;
};
const int maxe = 2500005;
const int maxv = 505;
edge e[maxe];
P pot[maxv];
int V,E,s,res,fa[maxv],height[maxv];
bool cmp(edge a1,edge a2)
{
return a1.dis<a2.dis;
}
void ini()
{
for(int i=1;i<=V;i++)
{
fa[i]=i;
height[i]=0;
}
}
int findfa(int a)
{
if(fa[a]==a) return a;
return fa[a]=findfa(fa[a]);
}
bool same(int a,int b)
{
return findfa(a)==findfa(b);
}
void unite(int a,int b)
{
int faa=findfa(a),fab=findfa(b);
if(height[faa]<height[fab])
fa[faa]=fab;
else
{
fa[fab]=faa;
if(height[faa]==height[fab]) height[faa]++;
}
}
double Kruscal()
{
priority_queue<double> pq;
sort(e+1,e+E+1,cmp);
ini();
for(int i=1;i<=E;i++)
{
edge nowe=e[i];
if(!same(e[i].v,e[i].u))
{
unite(e[i].v,e[i].u);
pq.push(e[i].dis);
}
}
for(int i=1;i<s;i++)
{
pq.top();pq.pop();
}
if(pq.empty()) return 0;
return pq.top();
}
double get_dis(P a,P b)
{
return sqrt((a.first-b.first)*(a.first-b.first)+(a.second-b.second)*(a.second-b.second));
}
int main()
{
//freopen("in.txt","r",stdin);
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&s,&V); //已经有卫星通讯的城市数和点数
for(int i=1;i<=V;i++)
scanf("%d%d",&pot[i].first,&pot[i].second);
int th=0;
for(int i=1;i<=V;i++)
for(int j=1;j<i;j++)
{
th++;
e[th].u=i;e[th].v=j;e[th].dis=get_dis(pot[i],pot[j]);
}
E=th;
printf("%0.2f\n",Kruscal()); //这里必须用%0.2f输出 不知道为什么
}
return 0;
}