HDU - 2682 

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",&times);
    while(times--){
        scanf("%d",&n);
        for(int i=0;i<n;i++){
            scanf("%d",&hp[i]);
        }
        init();
        printf("%d\n",kruskal());
    }
    return 0;
} 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章