当先锋百科网

首页 1 2 3 4 5 6 7

In order to prepare the “The First National ACM School Contest” (in 20??) the major of the city
decided to provide all the schools with a reliable source of power. (The major is really afraid of
blackoutsJ). So, in order to do that, power station “Future” and one school (doesn’t matter which one)
must be connected; in addition, some schools must be connected as well.
You may assume that a school has a reliable source of power if it’s connected directly to “Future”,
or to any other school that has a reliable source of power. You are given the cost of connection between
some schools. The major has decided to pick out two the cheapest connection plans – the cost of the
connection is equal to the sum of the connections between the schools. Your task is to help the major
— find the cost of the two cheapest connection plans.
Input
The Input starts with the number of test cases, T (1 < T < 15) on a line. Then T test cases follow. The
first line of every test case contains two numbers, which are separated by a space, N (3 < N < 100)
the number of schools in the city, and M the number of possible connections among them. Next M
lines contain three numbers Ai
, Bi
, Ci
, where Ci
is the cost of the connection (1 < Ci < 300) between
schools Ai and Bi
. The schools are numbered with integers in the range 1 to N.
Output
For every test case print only one line of output. This line should contain two numbers separated by a
single space – the cost of two the cheapest connection plans. Let S1 be the cheapest cost and S2 the
next cheapest cost. It’s important, that S1 = S2 if and only if there are two cheapest plans, otherwise
S1 < S2. You can assume that it is always possible to find the costs S1 and S2.
Sample Input
2
5 8
1 3 75
3 4 51
2 4 19
3 2 95
2 5 42
5 4 31
1 2 9
3 5 66
9 14
1 2 4
1 8 8
2 8 11
3 2 8
8 9 7
8 7 1
7 9 6
9 3 2
3 4 7
3 6 4
7 6 2
4 6 14
4 5 9
5 6 10
Sample Output
110 121
37 37
题意:
找最小生成树,和次最小生成树,
用kruskal算法,先求出最小数,并把每个路径标记,
然后再用相同的方法求次短路,具体就是:每次去掉一个标记过的边,然后遍历完,找到这个时候的最短路,一共去掉n-1条边,依次遍历找到当时的最短路,最后再在其中找最小的那个,就是次短路了

#include <cstdio>
#include <cmath>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int N=888;
int MAX=0x3f3f3f3f;
int n,m;
int dist[N],map[N][N];
int biao[N];
int sum[N];
int x[N],y[N];
int mm[N];
int pre[N];
struct node{
	int u,v,w;
}a[N*(N-1)/2];
bool cmp(node a,node b)
{
	return a.w<b.w;
}
int find(int x)
{
	if(pre[x]==x)
	return x;
	else
	return pre[x]=find(pre[x]);
}
int judge(int u,int v)
{
	int fx=find(u);
	int fy=find(v);
	if(fx!=fy)
	{
		pre[fx]=fy;
		return 1;
	}
	return 0;
}
void unit()
{
	for(int i=1;i<=n;i++)
	{
		pre[i]=i;
	}
}
int main()
{
   int t;
   cin>>t;
   while(t--)
   {
   	cin>>n>>m;
   	unit();//每个点的根节点是自己
   	memset(biao,0,sizeof(biao));
   	for(int i=0;i<m;i++)
   	{
   	  cin>>a[i].u>>a[i].v>>a[i].w;
	}
	sort(a,a+m,cmp);
	int ans=0,num=0;
	for(int i=0;i<m;i++)
	{
		if(judge(a[i].u,a[i].v))
		{
			ans+=a[i].w;
			num++;
			biao[i]=1;
			if(num==n-1)
			break;
		}
	}
	int minn=ans;
	int minnn=MAX;
	for(int i=0;i<m;i++)
	{
		ans=0,num=0;
		if(biao[i]==1)//去掉一条标记过的边
		{
			unit();//重新初始化
			for(int j=0;j<m;j++)
			{
				if(i==j)
				continue;
		    if(judge(a[j].u,a[j].v))
	    	{
			ans+=a[j].w;
			num++;
			
			if(num==n-1)
			{
				minnn=min(minnn,ans);
					break;
			}
		
	    	}
			}
		}
	}
	   cout<<minn<<" "<<minnn<<endl;
   }
    return 0;
}