Tree
description:
There are N (2<=N<=600) cities,each has a value of happiness,we consider two cities A and B whose value of happiness are VA and VB,if VA is a prime number,or VB is a prime number or (VA+VB) is a prime number,then they can be connected.What’s more,the cost to connecte two cities is Min(Min(VA , VB),|VA-VB|).
Now we want to connecte all the cities together,and make the cost minimal.
Input
The first will contain a integer t,followed by t cases.
Each case begin with a integer N,then N integer Vi(0<=Vi<=1000000).
Output
If the all cities can be connected together,output the minimal cost,otherwise output “-1”;
Sample Input
2
5
1
2
3
4
5
4
4
4
4
4
Sample Output
4
-1
题目大意:
所有的城市有一个快乐值Vi,城市A和B认为是连接的,如果Va或者Vb或者Va+Vb为素数。同时这个权值为,Min(Min(VA , VB),|VA-VB|)。现在求这些城市连接最小代价。(求这个图的最小生成树)。
解题思路:
1.最小生成树问题,这里由于要先判断城市间有没有连接以及连接的权值,所以后面采用Kruskal算法更合适一些。
2.在求边的权值的时候,由于要多次判断素数。因此可以采用素数打表的方式,预先求出0~2000001范围内的全部素数。这样会大大加快程序整体速度!
源代码:
#include<iostream>
#include<stdio.h>
#include<vector>
#include<algorithm>
#include<string.h>
using namespace std;
int n,e;
int fa[605];
int hp[605];
bool prime[2000010];
struct edg{
int start,end;
int cost;
bool operator < (const edg& a) const{
return cost<a.cost;
}
};
edg roads[360000];
int find(int x){
int r=x;
while(r!=fa[r])
r=fa[r];
int i=x,j;
while(fa[i]!=r){
j=fa[i];
fa[i]=r;
i=j;
}
return r;
}
int kruskal(){
if(e<n-1){
return -1;
}
for(int i=0;i<n;i++)
fa[i] = i;
sort(roads,roads+e);
int now_choose=0,total_cost = 0;
for(int i=0;i<e;i++){
int fs = find(roads[i].start);
int fe = find(roads[i].end);
if(fs!=fe){
fa[fs] = fe;
total_cost+=roads[i].cost;
now_choose++;
}
if(now_choose==n-1)
break;
}
if(now_choose<n-1)
return -1;
return total_cost;
}
void Get_prime(){
int i,j;
memset(prime,true,sizeof(prime));
prime[0]=prime[1]=false;
for(i=2;i<2000010;i++)
if(prime[i])
for(j=i<<1;j<2000010;j+=i)
prime[j]=false;
}
void init(){
e = 0;
for(int i=0;i<n;i++){
for(int j=i+1;j<n;j++){
if(prime[hp[i]] || prime[hp[j]] || prime[hp[i]+hp[j]] ){
roads[e].start = i;
roads[e].end = j;
roads[e].cost = min( min(hp[i],hp[j]), abs(hp[i]-hp[j]) );
e++;
//cout<<i<<" "<<j<<" "<<roads[e].cost<<endl;
}
}
}
}
int main(){
int times;
Get_prime();
scanf("%d",×);
while(times--){
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%d",&hp[i]);
}
init();
printf("%d\n",kruskal());
}
return 0;
}