HDU

来源:互联网 发布:php可以开发app吗 编辑:程序博客网 时间:2024/05/15 21:48

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;} 
原创粉丝点击