天天看點

LightOJ1029-Civil and Evil Engineer-生成樹

題目大意:給你一張圖,求它的最小生成樹和最大生成樹的的總費用/2;

題目解析: 用prime算法即可,求最小生成樹的時候,隻要每次取出長度目前長度最小的那條邊,并且維護dist[]就可以了,因為是樹狀結構,肯定不會有環,最大生成樹也是類似;

AC代碼:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
using namespace std;
const int inf=0x3fffffff;
int graph1[110][110],graph2[110][110],dist[110],n;
bool vis[110];
int min_prime()
{
	int sum=0,i,j,k,temp;
	memset(vis,0,sizeof(vis));
	vis[0]=1;
	for(i=1;i<=n;i++)
	{
		dist[i]=graph1[0][i];
	}
	for(k=1;k<=n;k++)
	{
		temp=inf;
		j=-1;
		for(i=1;i<=n;i++)
		{
			if(!vis[i]&&dist[i]<temp)
			{
				temp=dist[i];
				j=i;
			}
		}
		if(j==-1)
			return sum;
		sum+=temp;
		vis[j]=1; 
		for(i=1;i<=n;i++)
		{
			if(!vis[i]&&dist[i]>graph1[j][i])
			{
				dist[i]=graph1[j][i];
			}
		}
	}
	return sum;
}
int max_prime()
{
	int sum=0,i,j,k,temp;
	memset(vis,0,sizeof(vis));
	vis[0]=1;
	for(i=1;i<=n;i++)
	{
		dist[i]=graph2[0][i];
	}
	for(k=1;k<=n;k++)
	{
		temp=0;
		j=-1;
		for(i=1;i<=n;i++)
		{
			if(!vis[i]&&dist[i]>temp)
			{
				temp=dist[i];
				j=i;
			}
		}
		if(j==-1)
			return sum;
		sum+=temp;
		vis[j]=1; 
		for(i=1;i<=n;i++)
		{
			if(!vis[i]&&dist[i]<graph2[j][i])
			{
				dist[i]=graph2[j][i];
			}
		}
	}
	return sum;
}
int main()
{
	int cas,c,u,v,w,i,j;
	scanf("%d",&cas);
	for(c=1;c<=cas;c++)
	{
		memset(graph2,0,sizeof(graph1));
		for(i=0;i<110;i++)
			for(j=0;j<110;j++)
				graph1[i][j]=inf;
		scanf("%d",&n);
		while(scanf("%d%d%d",&u,&v,&w)&&(u+v+w)!=0)
		{
			graph1[v][u]=graph1[u][v]=min(w,graph1[u][v]);
			graph2[v][u]=graph2[u][v]=max(w,graph2[u][v]);
		}
		int min_cost=min_prime();
		int max_cost=max_prime();
		if((max_cost+min_cost)%2==1)
			printf("Case %d: %d/2\n",c,max_cost+min_cost);
		else 
			printf("Case %d: %d\n",c,(max_cost+min_cost)/2);
	} 
	return 0;
}