题目【USACO 2007 Dec S】 Building Roads
先贴惨状
这么一大片的段错误,没错,就是犯了你所想的那样最愚蠢的错误————数组开小了。
没仔细读题,代码实现的过程中数组开小了,反复检查了很多遍,还认为自己没有错,最后发现竟然是这个问题,气的我分号都没打就提交了,于是ce了(乐)。
让人桑心的是,加了分号以后,竟然还wa了两发,后面意识到了是结构体排序那里的错误。
再就是sqrt那里的精度问题,就这几个错误,希望大家也注意。
不多说,上思路
是一道一读就知道要用最小生成树的题(嘤嘤嘤,伦家只会写这种啦)该说不说翻译要了我点时间(数组越界问题就是这么来的,哭)
ok既然是最小生成树,那必然是要排序的,因此我们需要一个结构体数组,存入每个点与每个点之间的距离,再来选取最适合添加的道路,至于已经连通的道路?赋0就行了啦大叔。
思路就到这里吧,嗯?什么?你说为什么没了?拜托,这真的只是一道用了浮点数的板子题啦(所以我为什么错这么多次?)
咳咳,抛开我菜不谈,该上代码了
因为有点烦重名,所以没有使用std的命名空间,个人喜好啦。
#define ll long long
#define endl "\n"
const int MAX=1e6+5;
int n,m;
int f[MAX];//这个作用懂得都懂
int x[MAX],y[MAX];//存储每个点的位置信息
struct kk{
int x,y;
double dis;
}pp[MAX];//distance 距离
bool cmp(kk x, kk y){
if (x.dis == y.dis) return x.x < y.x;//关于因为缺少这一条语句而wa了一发这件事
return x.dis < y.dis;//最小,自然是升序排序
}
int find(int x){
return x==f[x]?x:f[x]=find(f[x]);//划重点
}
int main(){
std::ios::sync_with_stdio(false);
std::cin.tie(0),std::cout.tie(0);
std::cin>>n>>m;
int cnt=0;
for(int i=1;i<=n;i++){
std::cin>>x[i]>>y[i];
f[i]=i;
}
for(int i=1;i<=n;i++){
for(int j=i+1;j<=n;j++){
pp[++cnt].x=i;
pp[cnt].y=j;
pp[cnt].dis=(double)(sqrt((double)(x[i]-x[j])*(x[i]-x[j])+(double)(y[i]-y[j])*(y[i]-y[j])));
}//注意double!!!
}
for(int i=1;i<=m;i++){
int v,u;
std::cin>>v>>u;
pp[++cnt].x=v;
pp[cnt].y=u;
pp[cnt].dis=0;
}
std::sort(pp+1,pp+cnt+1,cmp);
double sum=0.0;
int ans=0;
for(int i=1;i<=cnt;i++){
if(find(pp[i].x)!=find(pp[i].y)){
f[find(pp[i].x)]=find(pp[i].y);//很多地方都想加注释,结果似乎真的没啥好说的
sum+=pp[i].dis;//这题真的太板子了,我真的是太菜了
}
}
std::cout<<std::fixed<<std::setprecision(2)<<sum<<endl;
return 0;
}
划重点那里,是希望如果有人和我一样查找还不会用递归的,请一定记下来背死了,不然会超时,还会被学长训(小声bb)
好了,到此为止了,大概写了有一个礼拜了,现在才来写博客,没办法,太懒了,如果看到了这里,祝你cf上大分!