次小生成树模板(坑惨了)

In order to prepare the “The First National ACM School Contest” (in 20??) the major of the city
decided to provide all the schools with a reliable source of power. (The major is really afraid of
blackoutsJ). So, in order to do that, power station “Future” and one school (doesn’t matter which one)
must be connected; in addition, some schools must be connected as well.
You may assume that a school has a reliable source of power if it’s connected directly to “Future”,
or to any other school that has a reliable source of power. You are given the cost of connection between
some schools. The major has decided to pick out two the cheapest connection plans – the cost of the
connection is equal to the sum of the connections between the schools. Your task is to help the major
— find the cost of the two cheapest connection plans.
Input
The Input starts with the number of test cases, T (1 < T < 15) on a line. Then T test cases follow. The
first line of every test case contains two numbers, which are separated by a space, N (3 < N < 100)
the number of schools in the city, and M the number of possible connections among them. Next M
lines contain three numbers Ai
, Bi
, Ci
, where Ci
is the cost of the connection (1 < Ci < 300) between
schools Ai and Bi
. The schools are numbered with integers in the range 1 to N.
Output
For every test case print only one line of output. This line should contain two numbers separated by a
single space – the cost of two the cheapest connection plans. Let S1 be the cheapest cost and S2 the
next cheapest cost. It’s important, that S1 = S2 if and only if there are two cheapest plans, otherwise
S1 < S2. You can assume that it is always possible to find the costs S1 and S2.
Sample Input
2
5 8
1 3 75
3 4 51
2 4 19
3 2 95
2 5 42
5 4 31
1 2 9
3 5 66
9 14
1 2 4
1 8 8
2 8 11
3 2 8
8 9 7
8 7 1
7 9 6
9 3 2
3 4 7
3 6 4
7 6 2
4 6 14
4 5 9
5 6 10
Sample Output
110 121
37 37

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#define maxn 105
using namespace std;
const int inf=0x3f3f3f3f3f;
int maxe[maxn][maxn];
int used[maxn][maxn];
int n,m;
int pre[maxn];
int map[maxn][maxn];
void init()
{
    memset(map,inf,sizeof(map));
    for(int i=0;i<n;i++)map[i][i]=0;
    memset(used,0,sizeof(used));
    memset(maxe,0,sizeof(used));
    for(int i=0;i<n;i++)pre[i]=i;
}

int prim()
{
    int mindis;
    int dis[maxn];
    int vis[maxn];
    int ans=0;
    memset(vis,0,sizeof(vis));
    for(int i=1;i<=n;i++)
    {
        pre[i]=1;
        dis[i]=map[1][i];
    }
    pre[1]=0;
    dis[1]=0;
    vis[1]=1;
    for(int i=2;i<=n;i++)
    {
        mindis=inf;
        int k=-1;
        for(int j=1;j<=n;j++)
        {
            if(!vis[j]&&mindis>dis[j])
            {
                mindis=dis[j];
                k=j;
            }
        }
        ans+=mindis;
        vis[k]=1;
        used[pre[k]][k]=used[k][pre[k]]=1;
        for(int j=1;j<=n;j++)
        {
            if(!vis[j]&&map[j][k]<dis[j])
            {
                dis[j]=map[j][k];
                pre[j]=k;
            }
            if(vis[j]&&j!=k)maxe[j][k]=maxe[k][j]=max(maxe[pre[k]][j],dis[k]);
            //拒绝自环
        }
    }
    return ans;
}
int ans;
int umst()
{
    int mindis=inf;
    for(int i=1;i<=n;i++)
    {
        for(int j=i+1;j<=n;j++)
        {
            if(!used[i][j]&&map[i][j]!=inf)
            {
               mindis=min(mindis,ans-maxe[i][j]+map[i][j]);
            }
        }
    }
    if(mindis==inf)return -1;
    return mindis;
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int a,b,c;
        scanf("%d%d",&n,&m);
        init();
        for(int i=0;i<m;i++)
        {
            scanf("%d%d%d",&a,&b,&c);
            map[a][b]=map[b][a]=c;
        }
            ans=prim();
            printf("%d %d\n",ans,umst());
    }

    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值