一、题目指路:
二、解题思路:
略(先将代码附上,思路等有时间再写)
三、源代码(已AC)
#include<bits/stdc++.h>
using namespace std;
int x[1100],y[1100];
int parent[1100];
int n,m;
struct Node{
int s;
int v;
double len;//顶点s,v之间的距离
};
bool operator<(const Node &a,const Node &b) //重载运算符,使优先队列变为最小堆
{
return a.len>b.len;
}
priority_queue<Node> q;//优先队列
//两点距离计算
double distance(int i,int j)
{
return sqrt(1.0*(x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]));
}
//找集合的根
int find(int x)
{
while(parent[x]>0) x=parent[x];
return x;
}
//合并
bool join(int i,int j)
{
int a=find(i);
int b=find(j);
if(a!=b) //不属于一个集合,可以合并
{
int temp=parent[a]+parent[b];
if(parent[a]<parent[b]) //a节点数多
{
parent[b]=a;
parent[a]=temp;
}
else
{
parent[a]=b;
parent[b]=temp;
}
return true;
}
else return false;
}
int main()
{
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
int N;
cin>>N;
int time=0;
while(N--)
{
if(time!=0) cout<<endl;
//前期输入工作
cin>>n;
for(int i=1;i<=n;i++) cin>>x[i]>>y[i];
for(int i=0;i<=n;i++) parent[i]=-1;//初始化
cin>>m;
int cnt=0;//已连接的边
int t1,t2;
while(m--){
cin>>t1>>t2;
if(join(t1,t2)) ++cnt;
}
priority_queue<Node> ep;
q=ep;//初始化优先队列
//开始整理每两个城镇的距离 ,并压入最小堆
for(int i=1;i<n;i++)
{
for(int j=i+1;j<=n;j++)
{
Node temp;
temp.s=i;
temp.v=j;
temp.len=distance(i,j);
q.push(temp);
}
}
while(cnt!=n-1&&!q.empty()) //kruskal算法,找到n-1条边即结束
{
Node t=q.top();
q.pop();
if(join(t.s,t.v)){
cout<<t.s<<" "<<t.v<<endl;
++cnt;
}
}
time++;
}
return 0;
}