求次小生成树

题目链接:https://cn.vjudge.net/contest/67265#problem/C

具体思路:和判断最小生成树是否唯一的思路差不多,首先跑一遍最小生成树,在求最小生成树的过程中记录任意两个点之间的最大权值,然后试着暴力,如果有一条边没有在最小生成树上,那么就先加上这条边的权值,再去减去两个端点之间的最大权值,求一个最小值,这就是次小生成树。

AC代码:

#include<iostream>
#include<string>
#include<cstring>
#include<iomanip>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<stdio.h>
#include<algorithm>
#include<set>
using namespace std;
# define ll long long
# define inf 0x3f3f3f3f
# define maxn 1000+100
# define eps 1e-6
int a[maxn][maxn];
int used[maxn][maxn];
int vis[maxn];
int maxx[maxn][maxn];
int father[maxn];
int dis[maxn];
int n,m;
int mst;
void init()
{
    memset(vis,0,sizeof(vis));
    memset(used,0,sizeof(used));
    memset(dis,inf,sizeof(dis));
    for(int i=1; i<=n; i++)
    {
        for(int j=1; j<=n; j++)
        {
            if(i==j)
                a[i][j]=0;
            else a[i][j]=inf;
            maxx[i][j]=0;
        }
    }
}
void prim()
{
    vis[1]=1;
    dis[1]=0;
    for(int i=1; i<=n; i++)
    {
        father[i]=1;
        dis[i]=a[1][i];
    }
    father[1]=-1;
    for(int i=1; i<n; i++)
    {
        int minn=inf,index=-1;
        for(int j=1; j<=n; j++)
        {
            if(vis[j]==0&&dis[j]<minn)
            {
                minn=dis[j];
                index=j;
            }
        }
        if(index==-1)return ;
        vis[index]=1;
        mst+=minn;
        if(father[index]!=-1)
            used[father[index]][index]=used[index][father[index]]=1;
        for(int j=1; j<=n; j++)
        {
            if(vis[j]==0&&dis[j]>a[index][j])
            {
                dis[j]=a[index][j];
                father[j]=index;
            }
            else if(vis[j]&&j!=index)
            {
                maxx[index][j]=maxx[j][index]=max(maxx[father[index]][j],dis[index]);
            }
        }
    }
}
int judge()
{
    int ans=inf;
    for(int i=1; i<=n; i++)
    {
        for(int j=1+i; j<=n; j++)
        {
            if(i==j)continue;
            if(!used[i][j]&&a[i][j]!=inf)
            {
               // cout<<i<<" "<<j<<" "<<a[i][j]<<" "<<maxx[i][j]<<endl;
                ans=min(ans,mst+a[i][j]-maxx[i][j]);
            }
        }
    }
    return ans;
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&m);
        init();
        int t1,t2,t3;
        for(int i=1; i<=m; i++)
        {
            scanf("%d%d%d",&t1,&t2,&t3);
            if(t3<a[t1][t2])
            {
                a[t2][t1]=a[t1][t2]=t3;
            }
        }
        mst=0;
        prim();
        printf("%d",mst);
        printf(" %d\n",judge());
    }
    return 0;
}


 

posted @ 2018-11-10 16:56  Let_Life_Stop  阅读(221)  评论(0编辑  收藏  举报