思路:
比较典型的求最小生成树,利用K算法或者P算法,如果在输入时两个村庄的修建状态为 已修建,那么我这里的做法是让他们之间的权值为 0,即修建费用为 0;然后套用算法就好了。
代码P算法:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 #include <cmath> 6 #include <cctype> 7 #include <algorithm> 8 #include <queue> 9 #include <stack> 10 #include <map> 11 #include <set> 12 using namespace std; 13 /* 集合之里:属于MST所构成的点集 反之亦然*/ 14 const int MAXN = 103; 15 const int INF = 0x3f3f3f3f; //最大值 16 int edge[MAXN][MAXN]; //邻接矩阵 17 int used[MAXN]; //标记这个点是否在最小生成树的集合里面 0 代表未加入 1 代表加入 18 int lowcost[MAXN]; //存放的是未被加入集合的 点 到 已经被加入集合的 点 的最短距离(如果集合里面的点和 多个集合之外的点相通 就取短的那个 这个数组伴随着加入点的变化而时刻变化着) 19 int N; 20 21 int prim(int start,int maxn) //假设 从 start 开始寻找MST, maxn 代表点的个数 22 { 23 used[start] = 1; 24 for(int i = 1; i <= maxn; i++) //刚开始只有start 这个点在集合里面 所以初始化这个数组为到集合之外的各个点的距离 ,如果没有则是无穷大(INF) 25 { 26 lowcost[i] = edge[start][i]; 27 } 28 int sumweight = 0; // MST 的权值 29 30 for(int i = 1; i <= maxn; i++) 31 { 32 int minn = INF ; //为找到最短的那条边 33 int v = -1; //标记找的那个点 34 for(int j = 1; j <= maxn; j++) //开始寻找集合之外得点到集合之里的点的最短边 35 { 36 if(used[j] == 0 && lowcost[j] < minn) //在集合之外的点寻找最短的边 37 { 38 minn = lowcost[j]; 39 v = j; 40 } 41 } 42 if(v != -1) //找到了 v 这个点 43 { 44 used[v] = 1; //标记已被使用 45 sumweight += lowcost[v]; //更新权值 46 for(int j = 1; j <= maxn; j++) //更新存放最短边的集合 47 { 48 if(used[j] == 0 && lowcost[j] > edge[v][j]) //在集合之外得点 寻找到集合之里各个点的最短边 更新数组 49 { 50 lowcost[j] = edge[v][j]; 51 } 52 } 53 } 54 } 55 return sumweight; 56 } 57 58 int main() 59 { 60 // freopen("in.cpp","r",stdin); 61 while(cin >> N && N) 62 { 63 memset(edge, 0x3f, sizeof(edge)); //清空为最大值 64 memset(used, 0, sizeof(used)); //刚开始所有的点都在集合之外 65 int M = N * (N - 1) / 2; 66 while(M--) 67 { 68 int u, v, w, ok; 69 scanf("%d%d%d%d",&u,&v,&w,&ok); 70 if(ok) w = 0; 71 edge[u][v] = edge[v][u] = w; 72 } 73 cout << prim(1, N) << endl; 74 } 75 return 0; 76 }
代码K算法:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 #include <cmath> 6 #include <cctype> 7 #include <algorithm> 8 #include <queue> 9 #include <stack> 10 #include <map> 11 #include <set> 12 using namespace std; 13 14 const int MAXN = 2e3+ 3; 15 int pre[MAXN]; 16 int n; 17 18 int Find(int x) 19 { 20 return x == pre[x] ? x :(pre[x] = Find(pre[x])); 21 } 22 23 structNode 24 { 25 int u, v, w; 26 }cy[103 * 103]; 27 28 int mycmp(Nodea,Nodeb) 29 { 30 return a.w < b.w; 31 } 32 33 void mst() 34 { 35 for(int i = 0 ; i < 102; i++) 36 pre[i] = i; 37 } 38 39 int kru() 40 { 41 int ans = 0; 42 for(int i = 1; i <= n * (n - 1) / 2; i++) 43 { 44 int fv = Find(cy[i].v); 45 int fu = Find(cy[i].u); 46 if(fv != fu) 47 { 48 pre[fv] = fu; 49 ans += cy[i].w; 50 } 51 } 52 return ans; 53 } 54 55 int main() 56 { 57 //freopen("in.cpp","r",stdin); 58 while(cin >> n && n) 59 { 60 mst(); 61 for(int i = 1; i <= n * (n - 1) / 2; i++) 62 { 63 int u, v, w, ok; 64 scanf("%d%d%d%d",&u,&v,&w,&ok); 65 if(ok) w = 0; 66 cy[i].u = u, cy[i].v = v, cy[i].w = w; 67 } 68 sort(cy + 1, cy + n * (n - 1) / 2 + 1, mycmp); 69 int ans = kru(); 70 printf("%d ",ans); 71 } 72 return 0; 73 }