次小生成树模板 WOJ 2675 新年趣事之游戏

描述

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

输入

第一行两个数N(2<=N<=500),M,分别表示国家的城市数和可以修建铁路的城市有多少对。

接下来M行,每行三个正整数Ai,Bi,Ci,表示城市Ai和Bi之间可以修建铁路,费用为Ci。

输出

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

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

样例输入

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

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

样例输出

Cost: 4
Cost: 4

输出样例2:
Cost: 4
Cost: -1

代码

prime

#include<bits/stdc++.h>
using namespace std;
const int N=1010;
int g[N][N],minc[N],fa[N],maxd[N][N];
bool con[N][N],vis[N];
int n,m;
int prime()
{
	memset(maxd,0,sizeof(maxd));
	memset(vis,false,sizeof(vis));
	memset(con,false,sizeof(con));
	int ans=0;
	for(int i=1;i<=n;i++)
	{
		minc[i]=g[1][i],fa[i]=1;
	}
	vis[1]=1;
	for(int i=1;i<n;i++)
	{
		int mi=0x3f3f3f3f,k=0;
		for(int j=2;j<=n;j++)
			if(!vis[j]&&minc[j]<mi)
				mi=minc[j],k=j;
		if(k==0) return -1;
		vis[k]=1;
		con[k][fa[k]]=con[fa[k]][k]=true;
		ans+=mi;
		maxd[fa[k]][k]=maxd[k][fa[k]]=mi;
		for(int j=1;j<=n;j++)
		{
			if(j!=k&&vis[j])
				maxd[k][j]=maxd[j][k]=max(maxd[j][fa[k]],minc[k]);
			if(!vis[j]&&g[k][j]<minc[j])
			{
				minc[j]=g[k][j];
				fa[j]=k;
			}
		}
	}
	return ans;
}
int main()
{
//	freopen("soc.cpp","r",stdin);
	scanf("%d%d",&n,&m);
	memset(g,0x3f,sizeof(g));
	for(int i=1,a,b,c;i<=m;i++)
	{
		scanf("%d%d%d",&a,&b,&c);
		g[a][b]=g[b][a]=c;
	}
	int ans=prime();
	printf("Cost: %d\n",ans);
	if(ans==-1){printf("Cost: -1");return 0;}
	int tmp=0x3f3f3f3f;
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			if(i==j||g[i][j]==0x3f3f3f3f) continue;
			if(!con[i][j]) tmp=min(tmp,ans-maxd[i][j]+g[i][j]);
		}
	}
	if(tmp==0x3f3f3f3f) printf("Cost: -1");
	else printf("Cost: %d",tmp);
}

Kruskal

#include<bits/stdc++.h>
#define N 500010
using namespace std; 
inline int rd()
{
	int data=0;int w=1;char ch=0;
    ch=getchar();
    while(ch!=‘-‘&&(ch<‘0‘||ch>‘9‘))ch=getchar();
    if(ch==‘-‘)w=-1,ch=getchar();
    while(ch>=‘0‘&&ch<=‘9‘)data=(data<<3)+(data<<1)+ch-‘0‘,ch=getchar();
    return data*w;
}
struct edge{
    int u,v,w;
}e[N];
int n,m,i,j,ans,num,psum; 
bool hash[N],bk;
int fa[N],E[N];
bool cmp(const edge a,const edge b)
{
	return a.w<b.w;
}
int find(int x)
{
    if (x!=fa[x]) fa[x]=find(fa[x]);
    return fa[x];
}
void kruscal()
{
    int i,a,b;
    for(i=1;i<=n;i++)fa[i]=i;
    num=0;
    for(i=1;i<=m;i++)
	{
        a=find(e[i].u);b=find(e[i].v);
        if(a!=b){
            fa[b]=a;ans+=e[i].w;
            num++;E[num]=i;
            if(num==n-1) 
				return;
        }
    }
}
void sec_kruscal()
{
    int nnum=0,a,b,i1;
    for(i1=1;i1<=n;i1++)fa[i1]=i1;
    for(i1=1;i1<=m;i1++)
      if(hash[i1])
	  {
            a=find(e[i1].u);b=find(e[i1].v);
            if(a!=b)
			{
                psum+=e[i1].w;fa[b]=a;
                nnum++;
                if(nnum==n-1)
				{
                    bk=true;return;
                }
            }
        }
}
int main()
{
    n=rd();m=rd();
    for(i=1;i<=m;i++)
	{
    	e[i].u=rd();e[i].v=rd();e[i].w=rd();
	}
    sort(e+1,e+m+1,cmp);
    ans=0;kruscal();
    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_kruscal();
        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;
}

次小生成树模板 WOJ 2675 新年趣事之游戏

上一篇:MyBatis入门


下一篇:Ztree树使用详解