Constructing Roads POJ - 2421 最小生成树之Kruskal算法
There are N villages, which are numbered from 1 to N, and you should build some roads such that every two villages can connect to each other. We say two village A and B are connected, if and only if there is a road between A and B, or there exists a village C such that there is a road between A and C, and C and B are connected.
We know that there are already some roads between some villages and your job is the build some roads such that all the villages are connect and the length of all the roads built is minimum.
We know that there are already some roads between some villages and your job is the build some roads such that all the villages are connect and the length of all the roads built is minimum.
Input
The first line is an integer N (3 <= N <= 100), which is the number of villages. Then come N lines, the i-th of which contains N integers, and the j-th of these N integers is the distance (the distance should be an integer within [1, 1000]) between village i and village j.
Then there is an integer Q (0 <= Q <= N * (N + 1) / 2). Then come Q lines, each line contains two integers a and b (1 <= a < b <= N), which means the road between village a and village b has been built.
Then there is an integer Q (0 <= Q <= N * (N + 1) / 2). Then come Q lines, each line contains two integers a and b (1 <= a < b <= N), which means the road between village a and village b has been built.
Output
You should output a line contains an integer, which is the length of all the roads to be built such that all the villages are connected, and this value is minimum.
Sample Input
3 0 990 692 990 0 179 692 179 0 1 1 2
Sample Output
179
题意:有不超过100个村庄,输入第一行一个数n表示村庄数,然后有n行每行都是第i个村庄与其他村庄的之间的距离,然后再一行有一个数m表示已经修建的道路数,然后往下m行,每行两个数表示在这两个村庄之间已经修建好了道路。
问在让所有的村庄都能够连接在一起的前提下至少还要修建多长的道路。
思路:题意可以以变换一下,已经修建好道路的村庄之间是可以不用再连接这两个村庄的,所以我们只需要求剩下的没连接在一起村庄进行最小生成数算法。
首先对村庄间的距离用一个二维数组保存,然后对已经修建好的村庄之间的道路进行标记,再对二维数组到容器的转发中把已经连在一起的村庄合并并不录入这个数据,最后在根据Kruskal算法进行运算。
代码:
1 #include <cstdio> 2 #include <fstream> 3 #include <algorithm> 4 #include <cmath> 5 #include <deque> 6 #include <vector> 7 #include <queue> 8 #include <string> 9 #include <cstring> 10 #include <map> 11 #include <stack> 12 #include <set> 13 #include <sstream> 14 #include <iostream> 15 #define mod 998244353 16 #define eps 1e-6 17 #define ll long long 18 #define INF 0x3f3f3f3f 19 using namespace std; 20 21 //u表示起点,v表示终点,cost表示花费 22 struct node 23 { 24 int u,v; 25 double cost; 26 }; 27 //排序,从小到大 28 bool cmp(node a,node b) 29 { 30 return a.cost<b.cost; 31 } 32 //存放边的信息 33 vector<node> ve; 34 35 //fa表示当前i的最远祖先 36 int fa[110]; 37 //初始化fa,开始时自己是自己的祖先 38 void init(int qwq) 39 { 40 for(int i=0;i<=qwq;i++) 41 { 42 fa[i]=i; 43 } 44 } 45 //查找最远祖先,同时进行路径压缩 46 int find(int x) 47 { 48 if(fa[x]==x) 49 { 50 return x; 51 } 52 return fa[x]=find(fa[x]); 53 } 54 //判断最远祖先是否相同 55 bool che(int x,int y) 56 { 57 return find(x)==find(y); 58 } 59 //合并x,y,把他们放到同一个家族中 60 void mer(int x,int y) 61 { 62 if(!che(x,y)) 63 { 64 fa[fa[x]]=fa[y]; 65 } 66 return ; 67 } 68 int n,m; 69 //ma用于保存村庄之间的距离 70 int ma[105][105]; 71 //bj用于标记已经连接的村庄编号 72 int bj[105][105]; 73 int main() 74 { 75 scanf("%d",&n); 76 //初始化 77 init(n); 78 for(int i=1;i<=n;i++) 79 { 80 for(int j=1;j<=n;j++) 81 { 82 scanf("%d",&m); 83 ma[i][j]=m; 84 } 85 } 86 int a,b; 87 //初始化bj 88 memset(bj,0,sizeof(bj)); 89 scanf("%d",&m); 90 for(int i=0;i<m;i++) 91 { 92 scanf("%d %d",&a,&b); 93 //标记, 94 bj[a][b]=1; 95 bj[b][a]=1; 96 } 97 node no; 98 for(int i=2;i<=n;i++) 99 { 100 for(int j=1;j<i;j++) 101 { 102 //当村庄之间没有道路时 103 if(bj[i][j]==0) 104 { 105 no.u=i; 106 no.v=j; 107 no.cost=ma[i][j]; 108 ve.push_back(no); 109 } 110 else 111 {//当村庄之间有道路时,合并这两个村庄 112 mer(i,j); 113 } 114 } 115 } 116 int ans=0; 117 //排序 118 sort(ve.begin(),ve.end(),cmp); 119 for(int i=0;i<ve.size();i++) 120 { 121 //当两个村庄之间没有连接时 122 if(!che(ve[i].u,ve[i].v)) 123 { 124 //合并 125 mer(ve[i].u,ve[i].v); 126 ans+=ve[i].cost; 127 } 128 } 129 printf("%d\n",ans); 130 //清除容器内存 131 ve.clear(); 132 }