https://www.luogu.com.cn/problem/P2872
就是求一个点到其他所有点构成的边,以及其距离是多少。
所以要对应,第 i,j个点。Union的是第i,j这俩序号,而不是点,因为i点由x,y两个坐标,就根据一个
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++)
就把每一个点和其他所有边都存进去了。
真腻害
哎,其实自己用bei的话,其实也能想出来。
1 2 3 4 5五个点,求1到其他点的距离,2到其他点的距离,3到其他点的距离,4到其他点的距离,5到其他点的距离,不就等于4+3+2+1=10=54/2=n(n-1)/2的吗。然后怎么变成程序,不就是for(int i=1;i<=n;i++) for(int j=i+1;j<=n;j++)这样遍历吗。
自己没有意识到是求边的两个点,两个点的距离,而不是存每个点的最短距离。然后就意识不到上面的操作了、
根本就不是看最短距离啊,因为你不知道和这个点连接有最短距离的那个点是谁,应该Union这两个。不就是上面的操作吗。。。
垃圾垃圾垃圾,谁赢了谁赢了,谁赢了哈哈哈
希望,能上岸,能成功,能有一颗少年的心把
//应该是求第i个点到第j个点的距离,而不是直接求最短距离
//思路总有一点偏颇
/*
直接求最短距离,不知道是求的谁的。但是我也不知道哪里错了。哎很烦。
先能写出来对的,再去搞错了的把
*/
/*
后面处理提前设置好的边的时候,再添加一条边,from to都不变,distance变成0
然后sort的时候这个就会排到最前面,然后前面这两个点Union了后面就不会Union了
我实在是想不到。。。。。
*/
#include<iostream>
#include<cstring>
#include<algorithm>
#include<math.h>
using namespace std;
const int N = 5000100;//~~是边的个数。。。。~~怎么来的你不知道?
int f[N];
int n,m;
struct nod{
int x,y;
}node[N];
struct Edge{
int from,to;
double distance;
}edge[N];
void Init()
{
for(int i=1;i<N;i++)
f[i]=i;
}
int find(int x)
{
if(x==f[x]) return x;
return f[x]=find(f[x]);
}
void Union(int a,int b)
{
a=find(a);b=find(b);
f[b]=a;
}
double getdistance(int i,int j)
{
int x1,x2,y1,y2;
x1=node[i].x;x2=node[j].x;
y1=node[i].y;y2=node[j].y;
double res;
res=(double)sqrt((double)(x1-x2)*(x1-x2)+(double)(y1-y2)*(y1-y2));
return res;
}
bool cmp(Edge a,Edge b)
{
if(a.distance==b.distance) return a.from<b.from;
return a.distance<b.distance;
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
{
scanf("%d%d",&node[i].x,&node[i].y);
}
//求第i个点到其余各点的距离。
int k=0;
for(int i=1;i<=n;i++)
{
for(int j=i+1;j<=n;j++)
{
edge[++k].from=i;
edge[k].to=j;
edge[k].distance=getdistance(i,j);
}
}
Init();
// for(int i=1;i<=k;i++)cout<<"("<<node[edge[i].from].x<<","<<node[edge[i].from].y<<")到("<<node[edge[i].to].x<<","<<node[edge[i].to].y<<")的距离是"<<edge[i].distance<<endl;
for(int i=1;i<=m;i++)
{
int p,q;
scanf("%d%d",&p,&q);
Union(p,q);
edge[++k].from=p;
edge[k].to=q;
edge[k].distance=0;
}
double res=0;
sort(edge+1,edge+1+k,cmp);
// for(int i=1;i<=k;i++)cout<<"("<<node[edge[i].from].x<<","<<node[edge[i].from].y<<")到("<<node[edge[i].to].x<<","<<node[edge[i].to].y<<")的距离是"<<edge[i].distance<<endl;
for(int i=1;i<=k;i++)
{
int a=edge[i].from,b=edge[i].to;
int roota=find(a),rootb=find(b);
if(roota!=rootb)
{
// cout<<"当前节点为("<<node[a].x<<","<<node[a].y<<")和("<<node[b].x<<","<<node[b].y<<")的距离为"<<edge[i].distance<<endl;
res+=edge[i].distance;
f[roota]=rootb;
}
}
//cout<<endl;
printf("%.2lf",res);
}
自己写的:
#include<iostream>
#include<cstring>
#include<algorithm>
#include<math.h>
using namespace std;
const int N = 5000001; //这个怎么来的?1000*1000/2,你值得拥有。
struct node{
int x,y;
}point[N];
struct nod{
int point1,point2;
double dis;
bool operator<(const nod &a)
{
if(a.dis==dis) return point1<a.point1;
return dis<a.dis;
}
}edge[N];
int f[N];
int n,m;
void Init()
{
for(int i=1;i<N;i++) f[i] = i;
}
int find(int x)
{
if(x==f[x]) return x;
return f[x] = find(f[x]);
}
void Union(int x,int y)
{
x=find(x);y=find(y);
f[x]= y;
}
double getdistance(int x1,int y1,int x2,int y2)
{
double res;
res=(double)sqrt((double)(x1-x2)*(x1-x2)+(double)(y1-y2)*(y1-y2));必须这样改,不然不对。好迷。
return res;
}
int main()
{
cin>>n>>m;
Init();
for(int i=1;i<=n;i++)
{
scanf("%d%d",&point[i].x,&point[i].y);
}
for(int i=1;i<=m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
Union(x,y);
}
// for(int i=1;i<=n;i++) cout<<f[i]<<" ";cout<<endl;
int k=0;
for(int i=1;i<=n;i++)
{
for(int j=i+1;j<=n;j++)
{
int x1,y1,x2,y2;
x1=point[i].x,y1=point[i].y;
x2=point[j].x,y2=point[j].y;
edge[++k].point1=i;
edge[k].point2=j;
edge[k].dis = getdistance(x1,y1,x2,y2);
}
}
// for(int i=1;i<=k;i++) cout<<edge[i].point1<<" "<<edge[i].point2<<" "<<edge[i].dis<<endl;
double res=0;
sort(edge+1,edge+1+k);
for(int i=1;i<=k;i++)
{
int a=edge[i].point1,b=edge[i].point2;
int roota=find(a),rootb=find(b);
if(roota!=rootb)
{
res+=edge[i].dis;
// cout<<a<<"!="<<b<<" dis="<<edge[i].dis<<endl;;
Union(roota,rootb);
}
//for(int i=1;i<=n;i++) cout<<f[i]<<" ";cout<<endl;
}
printf("%.2lf",res);
}