P2330 [SCOI2005]繁忙的都市 · 最小生成树

题解

首先,先了解一下什么是瓶颈生成树

定义无向图G,G的瓶颈生成树是一棵 “ 树上最大边权值 edge 在G的所有生成树中最小 ” 的生成树,这样的生成树可能不止一棵。瓶颈生成树的值为树上最大边权值 edge

例子:给出一个无向图G
P2330 [SCOI2005]繁忙的都市 · 最小生成树_第1张图片
其瓶颈生成树可能长这样:他们的值都是2
P2330 [SCOI2005]繁忙的都市 · 最小生成树_第2张图片

题意其实就是在问你最小的瓶颈生成树,
跑一遍最小生成树找最大边就可以了

了解两个定理:(想看证明可以去百度)
1.最小生成树一定是瓶颈生成树
2.瓶颈生成树不一定是最小生成树,最小生成树 = 最小瓶颈生成树


P2330 [SCOI2005]繁忙的都市 · 最小生成树_第3张图片


#include 
using namespace std;
const int INF=0x3f3f3f3f;
const int N=1e3+10;
int n,m;
int g[N][N];
int dis[N],vis[N];
int prim() {
    memset(dis, INF, sizeof dis);
    memset(vis, 0, sizeof vis);
    int res=0;
    for (int i = 0; i <n ; i++) {
        int f=-1;
        for (int j = 1; j <= n; j++) {
            if(!vis[j] && (f==-1 || dis[f]>dis[j]))
                f=j;
        }
        if(i)res=max(res,dis[f]);
        vis[f]=1;
        for (int j = 1; j <= n; j++) {
            dis[j]=min(dis[j],g[f][j]);
        }
    }
    return res;
}
int main()
{
    memset(g, INF, sizeof g);
    cin>>n>>m;
    for (int i = 1; i <= n; i++) {
        g[i][i]=0;
    }
    for (int i = 1,u,v,c; i <= m; i++) {
        cin>>u>>v>>c;
        g[u][v]=g[v][u]=c;
    }
    printf("%d %d\n",n-1,prim());
    return 0;
}

你可能感兴趣的:(洛谷)