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; }