题意:给你N个城镇,用最短的距离将他们连接起来,
然后M个数,每每两个代表已经有告诉公路了。
思路:只要将那个已经有公路的两个城镇之间的距离当做
0就行了,然后用最小生成树开始解决这一题。
开始用Prim()算法,发现保存不了最小生成树的组成
成员。然后用了克鲁斯卡尔算法。
还有题目要求输出来的答案不一定要按照那个顺序呢。
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=1001;
const int inf=1<<29;
const int maxm=maxn*maxn;
int vis[maxn][maxn];
int ff[100001];
struct Node
{
int from;
int to;
double w;
bool operator<(const Node &c)const
{
return w<c.w;
}
} E[maxm];
int p[maxn];
int n,m,kj;
double a[maxn],b[maxn];
int cha(int x)
{
if(p[x]==-1)
return x;
return p[x]=cha(p[x]);
}
struct Node1//用于保存最小生成树的成员。
{
int x,y;
double ks;
bool operator<(const Node1 &c)const
{
if(x==c.x)
return y<c.y;
return x<c.x;
}
} k[maxm];
void lxsb()
{
int cnt=0;
for(int i=0; i<kj; i++)
{
int x=cha(E[i].from);
int y=cha(E[i].to);
if(x!=y)
{
k[cnt].x=E[i].from;
k[cnt].y=E[i].to;
k[cnt].ks=E[i].w;
p[x]=y;
cnt++;
}
}
sort(k,k+cnt);
for(int i=0;i<cnt;i++)
if(k[i].ks==0)//为0代表这些城市不用输出。
continue;
else
printf("%d %d\n",k[i].x,k[i].y);
}
int main()
{
scanf("%d",&n);
{
memset(p,-1,sizeof(p));
memset(vis,0,sizeof(vis));
for(int i=1; i<=n; i++)
scanf("%lf%lf",&a[i],&b[i]);
kj=0;
scanf("%d",&m);
int x,y;
memset(ff,0,sizeof(ff));
for(int i=0; i<m; i++)
{
scanf("%d%d",&x,&y);
vis[x][y]=vis[y][x]=1;
}
for(int i=1; i<=n; i++)
for(int j=i+1; j<=n; j++)
{
if(vis[i][j]==1)
{
E[kj].from=i;
E[kj].to=j;
E[kj].w=0;
kj++;
continue;
}
double sum=(a[i]-a[j])*(a[i]-a[j])+(b[i]-b[j])*(b[i]-b[j]);
E[kj].from=i;
E[kj].to=j;
E[kj].w=sqrt(sum);
kj++;
}
sort(E,E+kj);
lxsb();
}
return 0;
}