九度 题目1249:次小生成树

题目描述:

最小生成树大家都已经很了解,次小生成树就是图中构成的树的权值和第二小的树,此值也可能等于最小生成树的权值和,你的任务就是设计一个算法计算图的最小生成树。

输入:

存在多组数据,第一行一个正整数t,表示有t组数据。
每组数据第一行有两个整数n和m(2<=n<=100),之后m行,每行三个正整数s,e,w,表示s到e的双向路的权值为w。

输出:

输出次小生成树的值,如果不存在输出-1。

样例输入:
2
3 3
1 2 1
2 3 2
3 1 3
4 4
1 2 2
2 3 2
3 4 2
4 1 2
样例输出:
4

6


///

突发奇想,不想用Dijkstra算法,就自己想了一下,每次将已经确定的最短路径的所有点与所有未确定的所有点之间的最短的那一条路径找到,然后把找到的最短路径相连的未确定的那个点加入到已经确定的集合中去,发现效率果然比Dijkstra低,毕竟每次要遍历n*n级数的边,边的遍历改成堆排序应该好很多,但估计也没有dijkstra效率高。。。。

找出最短路径就好办了,将每条在此路径上的边砍去,再求一次最短路径就好了。

效率不是很高,代码凌乱,不建议看了


#include<iostream>
using namespace std;
bool aluesd(bool*a,int n)
{
    while(n>0)
    {
        if(a[n]==false)
            return false;
        n--;
    }
    return true;
}
int kru(int v[102][102],int n,int m)
{
    int j,k;
    bool used[102]={false};
    used[1]=true;
    int vn[102][2];
    int vnlen=0;
    int minp1,minp2,min;
    bool fd=false;
    int sm=0;
    while(!aluesd(used,n))
        {
                min=2147483647;      
                fd=false;
                for(k=1;k<=n;k++)
                    if(used[k])
                for(j=1;j<=n;j++)
                {
                    if(v[k][j]>0&&v[k][j]<min&&!used[j])
                    {
                        min=v[k][j];
                        minp1=k;
                        minp2=j;
                        fd=true;
                    }
                }
 
                if(!fd)
                    break;
                else
                {
                    used[minp1]=true;
                    used[minp2]=true;
                    vn[vnlen][0]=minp1;
                    vn[vnlen][1]=minp2;
                    sm=sm+min;
                    vnlen++;
                }
         }
            if(fd)
                return sm;
            else
                return -1;
             
}
int main()
{
    int t;
    int j,k;
 
    while(cin>>t&&t!=0)
    {
        for(;t>0;t--)
        {
            int v[102][102]={0};
            int n,m,p1,p2;
            cin>>n>>m;
            for(j=0;j<m;j++)
            {
                cin>>p1>>p2;
                cin>>v[p1][p2];
                v[p2][p1]=v[p1][p2];
            }
            bool used[102]={false};
            used[1]=true;
            int vn[102][2];
            int vnlen=0;
            int minp1,minp2,min;
            bool fd=false;
            int sm=0;
            while(!aluesd(used,n))
            {
                min=2147483647;      
                fd=false;
                for(k=1;k<=n;k++)
                    if(used[k])
                for(j=1;j<=n;j++)
                {
                    if(v[k][j]>0&&v[k][j]<min&&!used[j])
                    {
                        min=v[k][j];
                        minp1=k;
                        minp2=j;
                        fd=true;
                    }
                }
 
                if(!fd)
                    break;
                else
                {
                    used[minp1]=true;
                    used[minp2]=true;
                    vn[vnlen][0]=minp1;
                    vn[vnlen][1]=minp2;
                    sm=sm+min;
                    vnlen++;
                }
            }
            if(!fd)
                cout<<-1<<endl;
            else
            {
                int vtemp,pt,pt2;
                pt=sm;
                bool iss=false;
                for(j=0;j<vnlen;j++)
                {
                    vtemp=v[vn[j][0]][vn[j][1]];
                    v[vn[j][0]][vn[j][1]]=0;
                    v[vn[j][1]][vn[j][0]]=0;
                    pt2=kru(v,n,m);
                    v[vn[j][0]][vn[j][1]]=vtemp;
                    v[vn[j][1]][vn[j][0]]=vtemp;
                    if(pt2!=-1)
                    {
                        if(!iss)
                          pt=pt2;
                        else
                            pt=pt<pt2?pt:pt2;
                        iss=true;
                    }
                }
                if(iss)
                    cout<<pt<<endl;
                else
                    cout<<-1<<endl;
            }
             
        }
    }
    return 0;
}
/**************************************************************
    Problem: 1249
    User: 午夜小白龙
    Language: C++
    Result: Accepted
    Time:260 ms
    Memory:1520 kb
****************************************************************/



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值