题目链接:
https://vjudge.net/problem/POJ-1751
题目大意:
有一个N个城市M条路的无向图,给你N个城市的坐标,然后现在该无向图已经有M条边了,问你还需要添加总长为多少的边能使得该无向图连通.输出需要添加边的两端点编号即可.
思路:
这里已经有部分边,要求剩下的MST,一开始没想到技巧,后来发现只要将已有的边的权值设置为0就可以直接求MST,这是一个很重要的技巧,如果已经确定的部分边,那就直接把这些边的权值设置成0,求出MST之后一定是包含这些边的MST。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 #include<queue> 7 #include<stack> 8 #include<map> 9 #include<set> 10 #include<sstream> 11 using namespace std; 12 typedef long long ll; 13 typedef pair<int, int> Pair; 14 const int maxn = 1e3 + 10; 15 const int INF = 1 << 30; 16 int dir[4][2] = {1,0,0,1,-1,0,0,-1}; 17 int T, n, m; 18 double Map[maxn][maxn];//存图 19 double lowcost[maxn]; 20 int mst[maxn]; 21 Pair a[maxn]; 22 void prim(int u)//最小生成树起点 23 { 24 for(int i = 1; i <= n; i++)//初始化两个数组 25 { 26 lowcost[i] = Map[u][i]; 27 mst[i] = u; 28 } 29 mst[u] = -1;//设置成-1表示已经加入mst 30 for(int i = 1; i <= n; i++) 31 { 32 double minn = INF; 33 int v = -1; 34 //在lowcost数组中寻找未加入mst的最小值 35 for(int j = 1; j <= n; j++) 36 { 37 if(mst[j] != -1 && lowcost[j] < minn) 38 { 39 v = j; 40 minn = lowcost[j]; 41 } 42 } 43 if(v != -1)//v=-1表示未找到最小的边, 44 {//v表示当前距离mst最短的点 45 //printf("%d %d %d ", mst[v], v, lowcost[v]);//输出路径 46 if(Map[mst[v]][v])printf("%d %d ", mst[v], v); 47 mst[v] = -1; 48 for(int j = 1; j <= n; j++)//更新最短边 49 { 50 if(mst[j] != -1 && lowcost[j] > Map[v][j]) 51 { 52 lowcost[j] = Map[v][j]; 53 mst[j] = v; 54 } 55 } 56 } 57 } 58 //printf("weight of mst is %d ", sum_mst); 59 } 60 int main() 61 { 62 cin >> n; 63 for(int i = 1; i <= n; i++)cin >> a[i].first >> a[i].second; 64 for(int i = 1; i <= n; i++) 65 { 66 for(int j = i; j <= n; j++) 67 { 68 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)); 69 } 70 } 71 cin >> m; 72 int x, y; 73 for(int i = 0; i < m; i++)//将已有的边的权值设置为0!!! 74 { 75 cin >> x >> y; 76 Map[x][y] = Map[y][x] = 0; 77 } 78 prim(1); 79 return 0; 80 }