次小生成树

#define MAXN 0x3f3f3f3f
using namespace std;

//#define debug

const int N=110;

int mmp[N][N],path[N][N];   //path求得是i-j的最大边权
int dis[N],pre[N];
bool vis[N],used[N][N];     //used记录是否在最小生成树中。
int n,m,mst;

inline void init(){
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            mmp[i][j]=MAXN;
        }
    }
}

int prim(){
    int mst=0;
    mm(path,0);mm(vis,0);mm(used,0);
    vis[1]=1;
    for(int i=1;i<=n;i++){
        dis[i]=mmp[1][i];
        pre[i]=1;
    }
    int cnt=1;
    while(cnt<n){
        int minn=MAXN,j;
        for(int i=1;i<=n;i++){
            if(!vis[i]&&dis[i]<minn){
                j=i;
                minn=dis[i];
            }
        }
        used[j][pre[j]]=used[pre[j]][j]=1;
        mst+=mmp[pre[j]][j];
        vis[j]=1;
        cnt++;
        for(int k=1;k<=n;k++){
            if(vis[k]&&k!=j)    //从k到j这条路径上最大边的权值
                path[k][j]=path[j][k]=max(path[k][pre[j]],dis[j]);
            if(!vis[k]&&dis[k]>mmp[j][k]){
                dis[k]=mmp[j][k];
                pre[k]=j;
            }
        }
    }
    return mst;
}

inline int second_tree(){
    int res=MAXN;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            if(i!=j&&!used[i][j]){
                res=min(res,mst-path[i][j]+mmp[i][j]);//删除树上权值最大的路径并且加上这条路径其它边
            }
        }
    }
    return res;
}

int main()
{
    #ifdef debug
    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
    #endif // debug

    int t;
    scanf("%d",&t);
    while(t--){
        scanf("%d%d",&n,&m);
        int u,v,w;
        init();
        for(int i=0;i<m;i++){
            scanf("%d%d%d",&u,&v,&w);
            mmp[u][v]=w;
            mmp[v][u]=w;
        }
        mst=prim();             //最小生成树
        int smst=second_tree(); //次小生成树
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_40679299/article/details/80722128