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