给定图G(V,E),以及其对应的一棵最小生成树,假定减少图中不属于最小生成树的一条边的权重,设计算法找出修改边后新图的最小生成树 ;给我完整代码
时间: 2023-06-16 08:05:09 浏览: 106
算法思路:
1. 首先,我们需要找到不属于最小生成树的一条边,可以通过遍历图中所有边,判断其是否在最小生成树中出现过,如果没有出现过,那么这条边就是我们需要修改的边。
2. 然后,我们需要将这条边的权值减少,这里可以直接在原图上修改,也可以将其复制一份进行修改。
3. 最后,我们需要重新求解最小生成树,可以使用 Prim 算法或者 Kruskal 算法。
代码实现(使用 Prim 算法):
```
#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;
const int INF = 0x3f3f3f3f;
struct Edge{
int to, weight;
Edge(int _to, int _weight): to(_to), weight(_weight){}
};
vector<Edge> G[100]; // 存储图的邻接表
bool used[100]; // 标记节点是否已被访问
int mincost[100]; // 存储从最小生成树出发到各个节点的最小边权值
int prim(int n){
memset(used, false, sizeof(used));
memset(mincost, INF, sizeof(mincost));
mincost[0] = 0;
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;
pq.push(make_pair(0, 0));
int res = 0;
while(!pq.empty()){
pair<int, int> p = pq.top(); pq.pop();
int v = p.second;
if(used[v]) continue;
used[v] = true;
res += p.first;
for(int i = 0; i < G[v].size(); i++){
int u = G[v][i].to;
int cost = G[v][i].weight;
if(!used[u] && cost < mincost[u]){
mincost[u] = cost;
pq.push(make_pair(mincost[u], u));
}
}
}
return res;
}
int main(){
int n, m;
cin >> n >> m;
// 读入图的邻接表
for(int i = 0; i < m; i++){
int a, b, c;
cin >> a >> b >> c;
G[a].push_back(Edge(b, c));
G[b].push_back(Edge(a, c));
}
// 计算原图的最小生成树
int original_mst = prim(n);
// 枚举每一条不在最小生成树中的边,找到权值最小的边
int min_edge_weight = INF;
int min_edge_u = -1, min_edge_v = -1;
for(int u = 0; u < n; u++){
for(int i = 0; i < G[u].size(); i++){
int v = G[u][i].to;
int w = G[u][i].weight;
if(mincost[u] != INF && mincost[v] != INF && mincost[u] + w == mincost[v]){
continue; // 如果这条边在原图的最小生成树中,就跳过
}
if(w < min_edge_weight){
min_edge_weight = w;
min_edge_u = u;
min_edge_v = v;
}
}
}
// 修改边权,重新计算最小生成树
G[min_edge_u][min_edge_v].weight -= min_edge_weight;
G[min_edge_v][min_edge_u].weight -= min_edge_weight;
int new_mst = prim(n);
// 输出结果
cout << "Original MST: " << original_mst << endl;
cout << "New MST: " << new_mst << endl;
return 0;
}
```
注意事项:
1. 这里使用了邻接表存储图,如果使用邻接矩阵存储图,那么修改边权的时间复杂度会变成 $O(n^2)$,不太适合大规模的图。
2. 在枚举不在最小生成树中的边时,我们需要判断这条边是否在原图的最小生成树中出现过,如果出现过就可以跳过,否则就比较这条边的权值和上一条最小边权的大小。