新年趣事之游戏

Description

xiaomengxian的哥哥是一个游戏迷,他喜欢研究各种游戏。这天,xiaomengxian到他家玩,他便拿出了自己最近正在研究的一个游戏给xiaomengxian看。这个游戏是这样的:一个国家有N个城市,有些城市之间可以建设铁路,并且不同城市之间建设铁路的费用各不相同。问如何用最小的费用,使整个国家的各个城市之间能够互相到达。另外,铁路是双向的。xiaomengxian心想,这不是太简单了吗?这就是经典的MST问题。他的哥哥说,这个当然不算什么。关键是它还要求费用第二小的方案,这真是让人伤脑筋。xiaomengxian想了很久,也没有想出来,你能帮助他吗? 
费用第二小的方案的定义为:与费用最小的方案不完全相同,且费用值除费用最小的方案外最小。

Input

第一行两个数N(2<=N<=500),M,分别表示国家的城市数和可以修建铁路的城市有多少对。 
接下来M行,每行三个正整数Ai,Bi,Ci,表示城市Ai和Bi之间可以修建铁路,费用为Ci。

Output

第一行:”Cost: “+一个整数,表示最小费用。(若不存在,输出-1) 
第二行:”Cost: “+一个整数,表示第二小费用。(若不存在,输出-1)

Sample Input

4 6
1 2 2
2 3 2
3 4 2
4 1 2
1 3 1
2 4 1

Sample Output

Cost: 4
Cost: 4

最小生成树的kruskal算法,
本题是求次小生成树,用到删边记录,记录最小生成树的每条边,在依次删除每条边,然后统计一下最小生成树,再搜寻一个最小值

下面是转载某大牛的代码当模版了:
#include<iostream>
using namespace std;

struct edge
{
    int x,y,c;
};
edge elist[250010];

int n,m,i,j,ans,num,psum;

bool hash[250010],bk;

int zu[501],e[501];
int cmp(const void *s,const void *t)
{
    edge i=*(edge *)s,j=*(edge *)t;
    return i.c-j.c;
}
int find(int x)
{
    if (x!=zu[x]) zu[x]=find(zu[x]);
    return zu[x];
}
void kruskal()
{
    int i,a,b;
    for (i=1;i<=n;i++) zu[i]=i;
    num=0;
    for (i=1;i<=m;i++)
    {
        a=find(elist[i].x);
        b=find(elist[i].y);
        if (a!=b)
        {
            zu[b]=a;
            ans+=elist[i].c;
            num++;
            e[num]=i;
            if (num==n-1) 
				return;
        }
    }
}
void sec_kruskal()
{
    int nnum=0,a,b,i1;
    for (i1=1;i1<=n;i1++) zu[i1]=i1;
    for (i1=1;i1<=m;i1++)
      if (hash[i1])
      {
            a=find(elist[i1].x);
            b=find(elist[i1].y);
            if (a!=b)
            {
                psum+=elist[i1].c;
                zu[b]=a;
                nnum++;
                if (nnum==n-1)
                {
                    bk=true;
                    return;
                }
            }
        }
}
int main()
{
    scanf("%d%d",&n,&m);

    for (i=1;i<=m;i++)
      scanf("%d%d%d",&elist[i].x,&elist[i].y,&elist[i].c);

    qsort(elist+1,m,sizeof(edge),cmp);
    ans=0;
    kruskal();
    printf("Cost: %d\n",ans);
    ans=0x7fffffff;
    memset(hash,1,sizeof(hash));
    for (i=1;i<=num;i++){
        hash[e[i]]=0;
        psum=0;
        bk=false;
        sec_kruskal();
        if (bk)
        {
            if (psum<ans) ans=psum;
        }
        hash[e[i]]=1;
    }
    if (ans==0x7fffffff) 
		 printf("Cost: %d\n",-1);
    else 
		printf("Cost: %d\n",ans);
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值