次小生成树

来源:互联网 发布:范伟 金马奖 知乎 编辑:程序博客网 时间:2024/04/30 06:51

次小生成树可由最小生成树换一条边得到。


次小生成树的步骤:


(1)先用Prime求出最小生成树T,在Prime的同时用一个矩阵max_edge[u][v]记录在T中连接任意两点u,v的唯一路径中权

值最大的那条边的权值。注意这里是很容易做到的,因为Prime是每次增加一个节点t,而设已经标了号的节点集合为S,则S

中所有节点到t的路径中最大权值的边就是当前加入的这条边。


(2)枚举最小生成树以外的边,并删除该边所在环上权值最大的边。


(3)取得的所有生成树中权值最小的一棵即为所求。


算法的时间复杂度为O(n^2)。



题目:http://poj.org/problem?id=1679


#include <iostream>#include <string.h>#include <stdio.h>using namespace std;const int N = 1005;const int INF = 1<<30;bool vis[N];bool used[N][N];int dist[N],pre[N];int map[N][N],max_edge[N][N];int ans1,ans2;int n,m;void Init(){    memset(vis,0,sizeof(vis));    memset(pre,0,sizeof(pre));    memset(dist,0,sizeof(dist));    memset(used,0,sizeof(used));    memset(max_edge,0,sizeof(max_edge));    for(int i=1; i<=n; i++)        for(int j=1; j<=n; j++)            map[i][j] = INF;}int Prime(int map[][N],int n){    int ans = 0;    for(int i=1; i<=n; i++)    {        dist[i] = map[1][i];        pre[i] = 1;    }    vis[1] = 1;    dist[1] = 0;    for(int i=1; i<=n; i++)    {        int k = 0;        int minval = INF;        for(int j=1; j<=n; j++)        {            if(!vis[j] && dist[j] < minval)            {                minval = dist[j];                k = j;            }        }        vis[k] = 1;        pre[k] = i;        used[i][k] = 0;        used[k][i] = 0;        ans += dist[k];        for(int j=1; j<=n; j++)        {            if(vis[j])                max_edge[k][j] = max_edge[j][k] = max(max_edge[pre[k]][j],map[pre[k]][k]);            if(!vis[j] && map[k][j] < dist[j])            {                dist[j] = map[k][j];                pre[j] = k;            }        }    }    return ans;}int Second_Prime(){    int ans = INF;    for(int i=1; i<=n; i++)    {        for(int j=1; j<=n; j++)        {            if(used[i][j])                ans = min(ans,ans1 + map[i][j] - max_edge[i][j]);        }    }    return ans;}int main(){    int T;    scanf("%d",&T);    while(T--)    {        scanf("%d%d",&n,&m);        Init();        if(n == 0) break;        for(int i=1; i<=m; i++)        {            int u,v,w;            scanf("%d%d%d",&u,&v,&w);            map[u][v] = map[v][u] = w;            used[u][v] = used[v][u] = 1;        }        ans1 = Prime(map,n);        ans2 = Second_Prime();        if(ans1 == ans2) puts("Not Unique!");        else printf("%d\n",ans1);    }    return 0;}



原创粉丝点击