“次小生成树类问题”模版

来源:互联网 发布:数据交换平台脱敏工具 编辑:程序博客网 时间:2024/05/21 08:36
#include<cstdio>#include<cmath>#include<cstring>#include<vector>#include<algorithm>using namespace std;const int maxn = 1000 + 10;struct Edge {  int x, y;  double d;  bool operator < (const Edge& rhs) const {    return d < rhs.d;  }};struct MST{    int n, m;//点数和边数    Edge e[maxn*maxn];//储存所有的边    int pa[maxn];//用于并查集,父指针    vector<int> G[maxn];//用于Dfs,储存生成树中每个点相邻的点    vector<double> C[maxn];//用于Dfs,储存相应的边的权    vector<int> nodes;//用于Dfs,储存已经遍历过的节点    double maxcost[maxn][maxn];//储存最小生成树中,u、v唯一路径上的最大权值    //这里是把无根树,转为了有根树,具体做法:    //在初始调用时Dfs(0,-1,0),然后后面节点拓展儿子时,不允许向回走    void dfs(int u, int fa, double facost){        //先对当前点同所有已访问过的节点,进行更新        for(int i = 0; i < nodes.size(); i++) {            int x = nodes[i];            maxcost[u][x] = maxcost[x][u] = max(maxcost[x][fa], facost);        }        nodes.push_back(u);        //再递归下一个点        for(int i = 0; i < G[u].size(); i++) {            int v = G[u][i];            if(v != fa) dfs(v, u, C[u][i]);        }    }    void init(int n){        this -> n = n;        m = 0;        memset(maxcost,0,sizeof(maxcost));        nodes.clear();        for(int i = 0; i < n; i++) { pa[i] = i; G[i].clear(); C[i].clear(); }    }    void AddEdge(int x,int y,double dist){        e[m++] = (Edge){x,y,dist};    }    int findset(int x) { return pa[x] != x ? pa[x] = findset(pa[x]) : x; }    double solve() {        sort(e, e+m);        int cnt = 0;        double ans = 0;        for(int i = 0; i < m; i++) {            int x = e[i].x, y = e[i].y, u = findset(x), v = findset(y);            double d = e[i].d;                if(u != v) {                    pa[u] = v;                    G[x].push_back(y); C[x].push_back(d);                    G[y].push_back(x); C[y].push_back(d);                    ans += d;                    if(++cnt == n-1) break;                }            }        return ans;    }};MST solver;


这个模版是我从LRJ例题代码中整理出来的,和之前的模版风格类似,写成结构体的形式,主要用与求出每对节点间的最小瓶颈路的最大边长maxcost[u][v]数组。

最小瓶颈路:给定加权无向图的两个节点u和v,求出从u到v的一条路径,使得路径上的最长边长最短。

这个maxcost数组很重要,因为定理:次小生成树一定可以由最小生成树加一条边再删一条边得到,而删的这条边的边长,就可由这个maxcost数组直接得到。

具体的求maxcost的思路,请参考《训练指南》。

使用时注意节点编号要从0开始,和边的dist的类型。时间复杂度O(n^2)

原创粉丝点击