记得上一次看图论都是5月份到6月份在准备比赛的时候的事了,最近在做一个pat的题,又遇见图论的题了,发现自己还是无法很灵活的来思考,故今天在http://wenku.baidu.com/link?url=xh_bpNdXCwUwRFqlFJNdmTil99yyTn3gaOkK5FSdGANE34hLoZhXIFj1Q8VYJHVfMxirWeuw8U3rmO2Vyg9j8P0Eflq-qjBN0_Zkub3xo-q 看了经典图论算法,顺便做个笔记方便以后自己复习
最小生成树
prim
点集合A,点集合B
集合A中初始情况下放置全部点
集合B中初始情况下没有点
从A中选择任意一个点放入B中
循环:
对B中所有点的所有在A中可用点进行遍历
找到最小值的点,累加这个值,并将该点从A放入B中
直至A中没有点,结束循环
我的代码比较麻烦,但是意思还是那个意思:
1 #include"iostream" 2 3 #include"cstring" 4 5 #include"set" 6 7 using namespace std; 8 9 10 11 int main(){ 12 13 //点到另一个点的权值 14 15 int map[101][101]; 16 17 //有哪些点 18 19 set<int> pts; 20 21 memset(map,0,sizeof(map)); 22 23 24 25 26 27 int n,x,y,weight; 28 29 cin>>n; 30 31 for(int i = 0;i < n;++i){ 32 33 cin>>x>>y>>weight; 34 35 pts.insert(x); 36 37 pts.insert(y); 38 39 map[x][y] = weight; 40 41 map[y][x] = weight; 42 43 } 44 45 46 47 set<int> res; 48 49 res.insert(*(pts.begin())); 50 51 pts.erase(pts.begin()); 52 53 54 55 int sum = 0; 56 57 while(!pts.empty()){ 58 59 set<int>::iterator itA,itB; 60 61 int minPoint,minWeight = 0x7fffffff; 62 63 for(itA = res.begin();itA != res.end();++itA){ 64 65 int pointA = *itA; 66 67 for(itB = pts.begin();itB != pts.end();++itB){ 68 69 int pointB = *itB; 70 71 if(map[pointA][pointB] != 0 && map[pointA][pointB] <= minWeight){ 72 73 minPoint = pointB; 74 75 minWeight = map[pointA][pointB]; 76 77 } 78 79 } 80 81 } 82 83 sum += minWeight; 84 85 res.insert(minPoint); 86 87 pts.erase(minPoint); 88 89 } 90 91 92 93 cout<<sum<<endl; 94 95 96 97 return 0; 98 99 }
测试数据如下:
输入
8
1 2 2
1 3 12
1 4 10
2 3 8
2 5 9
5 3 3
5 4 7
4 3 6
输出 19
kruskal:
排序所有权重
从小到大累加,如果对应的边导致累加过程中出现回路则跳过这条边
对于kruskal算法来说最麻烦的地方就是判断是否形成回路,这里会用到并查集的方式来解决问题:
并查集:
求取现在所有点的父节点。只要是同一个父节点就说明是处于同一个回路中。
1 #include"iostream" 2 3 #include"algorithm" 4 5 #include"cstring" 6 7 using namespace std; 8 9 typedef struct edge{ 10 11 int src; 12 13 int dst; 14 15 int weight; 16 17 }edge; 18 19 int comp(const void *a,const void *b){ 20 21 edge x = *(edge*)a,y = *(edge*)b; 22 23 return x.weight - y.weight; 24 25 } 26 27 int UFS[101]; 28 29 int find(int x){ 30 31 if(UFS[x] != x) 32 33 UFS[x] = find(UFS[x]); 34 35 return UFS[x]; 36 37 } 38 39 int main(){ 40 41 42 43 int n,x,y,weight; 44 45 cin>>n; 46 47 edge* edges = new edge[n]; 48 49 for(int i = 0;i < n;++i){ 50 51 cin>>x>>y>>weight; 52 53 edges[i].src = x; 54 55 edges[i].dst = y; 56 57 edges[i].weight = weight; 58 59 } 60 61 62 63 qsort(edges,n,sizeof(edge),comp); 64 65 for(int i = 0;i < 101;++i) 66 67 UFS[i] = i; 68 69 70 71 int sum = 0; 72 73 74 75 for(int i = 0;i < n;++i){ 76 77 edge temp = edges[i]; 78 79 int p = find(temp.dst); 80 81 int q = find(temp.src); 82 83 if(p != q){ 84 85 86 87 if(temp.dst > temp.src) //这里必须要对大小进行判断不然顺序会出错 88 89 UFS[temp.dst] = temp.src; 90 91 else UFS[temp.src] = temp.dst; 92 93 94 95 sum += temp.weight; 96 97 } 98 99 } 100 101 102 103 cout<<sum<<endl; 104 105 106 107 return 0; 108 109 }
当自己重新写一遍的时候才会发现问题所在。也希望大家能多多交流。
时间: 2024-11-06 22:48:54