题意:1-N个村庄建立高速公路(最小生成树),给出村庄坐标以及已经建立高速公路的村庄,求要在那些村庄间建立高速公路。
解题思路:将已经建立高速公路的村庄距离改成0,然后就是直接裸的最小生成树了。我这里是用prim算法。
/* ***********************************************
┆ ┏┓ ┏┓ ┆
┆┏┛┻━━━┛┻┓ ┆
┆┃ ┃ ┆
┆┃ ━ ┃ ┆
┆┃ ┳┛ ┗┳ ┃ ┆
┆┃ ┃ ┆
┆┃ ┻ ┃ ┆
┆┗━┓ 马 ┏━┛ ┆
┆ ┃ 勒 ┃ ┆
┆ ┃ 戈 ┗━━━┓ ┆
┆ ┃ 壁 ┣┓┆
┆ ┃ 的草泥马 ┏┛┆
┆ ┗┓┓┏━┳┓┏┛ ┆
┆ ┃┫┫ ┃┫┫ ┆
┆ ┗┻┛ ┗┻┛ ┆
************************************************ */
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
using namespace std;
#define inf 0x3f3f3f3f
#define ll long long
#define ull unsigned long long
#define maxn 1065
int Map[maxn][maxn],x[maxn],y[maxn],pre[maxn];
int n,q;
void prim()
{
int d[maxn],min,v;
int vis[maxn];
for(int i=1;i<=n;i++)
{
d[i]=Map[1][i];
vis[i]=0;
pre[i]=1;
}
vis[1]=1;
for(int i=1;i<=n;i++)
{
min=inf,v=0;
for(int j=1;j<=n;j++)
{
if(!vis[j] && min>d[j])
{
min=d[j];
v=j;
}
}
vis[v]=1;
if(Map[pre[v]][v]!=0)
printf("%d %d\n",pre[v],v);
for(int j=1;j<=n;j++)
{
if(!vis[j] && d[j]>Map[v][j])
{
d[j]=Map[v][j];
pre[j]=v;
}
}
}
}
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d%d",&x[i],&y[i]);
for(int j=1;j<=i;j++)
{
Map[i][j]=Map[j][i]=(x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]);
}
}
scanf("%d",&q);
while(q--)
{
int a,b;
scanf("%d%d",&a,&b);
Map[a][b]=Map[b][a]=0;
}
prim();
return 0;
}