Tree
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
题意:有n个点,每个点有一个权值,然后如果两个点a,b之间有连边当a、b、a+b中至少存在一个是素数,如果能连边,边的权值为 Min(Min(VA , VB),|VA-VB|),即a、b、|a+b|中的最小值,然后要我们求这n个的最小生成树,如果没法形成生成树就输出-1。
分析:先预处理出200000内的素数,然后对于任意两个点看是否能连边。然后跑一下kurskal就行了。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <queue>
#include <set>
#include <map>
#include <algorithm>
#include <math.h>
#include <vector>
using namespace std;
int n;
struct node {
int u,v,w;
bool operator <(const node &t)const {
return w<t.w;
}
}edge[605*605];//边集
int fa[1000006];//并查集
bool prime[2000005];//标记是否是素数
int a[605];
int find(int x){//并查集
return fa[x]==x?x:fa[x]=find(fa[x]);
}
void getprime(){//预处理出素数
memset (prime,true,sizeof (prime));
prime[0]=prime[1]=false;
for (int i=2;i<=2000000;i++){
if (prime[i]){
for (int j=i*2;j<=2000000;j+=i){
prime[j]=false;
}
}
}
}
int judge(int a,int b){//判断是否能连边
if (prime[a]||prime[b]||prime[a+b]){
return min((int)fabs(a-b),min(a,b));
}
return -1;//不能连边直接输出-1
}
int main()
{
getprime();//预处理
int T;
scanf ("%d",&T);
while (T--){
scanf ("%d",&n);
for (int i=0;i<n;i++){
scanf ("%d",&a[i]);
}
for (int i=0;i<=1000000;i++)fa[i]=i;//初始化
int cnt=0;
for (int i=0;i<n-1;i++){
for (int j=i+1;j<n;j++){
int w=judge(a[i],a[j]);
if (w!=-1){//判断能否加边
edge[cnt++]=(node){i,j,w};
}
}
}
sort(edge,edge+cnt);//排序
int sum=0;
int ans=0;
for (int i=0;i<cnt;i++){
int fu=find(edge[i].u);
int fv=find(edge[i].v);
if (fu!=fv){
sum++;
ans+=edge[i].w;
fa[fu]=fv;
}
if (sum==n-1)break;
}
if (sum!=n-1)printf ("-1\n");
else printf ("%d\n",ans);
}
return 0;
}