题目链接:
https://vjudge.net/problem/POJ-1751
题目大意:
有一个N个城市M条路的无向图,给你N个城市的坐标,然后现在该无向图已经有M条边了,问你还需要添加总长为多少的边能使得该无向图连通.输出需要添加边的两端点编号即可.
思路:
这里已经有部分边,要求剩下的MST,一开始没想到技巧,后来发现只要将已有的边的权值设置为0就可以直接求MST,这是一个很重要的技巧,如果已经确定的部分边,那就直接把这些边的权值设置成0,求出MST之后一定是包含这些边的MST。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<sstream>
using namespace std;
typedef long long ll;
typedef pair<int, int> Pair;
const int maxn = 1e3 + ;
const int INF = << ;
int dir[][] = {,,,,-,,,-};
int T, n, m;
double Map[maxn][maxn];//存图
double lowcost[maxn];
int mst[maxn];
Pair a[maxn];
void prim(int u)//最小生成树起点
{
for(int i = ; i <= n; i++)//初始化两个数组
{
lowcost[i] = Map[u][i];
mst[i] = u;
}
mst[u] = -;//设置成-1表示已经加入mst
for(int i = ; i <= n; i++)
{
double minn = INF;
int v = -;
//在lowcost数组中寻找未加入mst的最小值
for(int j = ; j <= n; j++)
{
if(mst[j] != - && lowcost[j] < minn)
{
v = j;
minn = lowcost[j];
}
}
if(v != -)//v=-1表示未找到最小的边,
{//v表示当前距离mst最短的点
//printf("%d %d %d\n", mst[v], v, lowcost[v]);//输出路径
if(Map[mst[v]][v])printf("%d %d\n", mst[v], v);
mst[v] = -;
for(int j = ; j <= n; j++)//更新最短边
{
if(mst[j] != - && lowcost[j] > Map[v][j])
{
lowcost[j] = Map[v][j];
mst[j] = v;
}
}
}
}
//printf("weight of mst is %d\n", sum_mst);
}
int main()
{
cin >> n;
for(int i = ; i <= n; i++)cin >> a[i].first >> a[i].second;
for(int i = ; i <= n; i++)
{
for(int j = i; j <= n; j++)
{
Map[i][j] = Map[j][i] = sqrt((a[i].first - a[j].first) * (a[i].first - a[j].first) + (a[i].second - a[j].second) * (a[i].second - a[j].second));
}
}
cin >> m;
int x, y;
for(int i = ; i < m; i++)//将已有的边的权值设置为0!!!
{
cin >> x >> y;
Map[x][y] = Map[y][x] = ;
}
prim();
return ;
}