题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2682
#include <stdio.h>
#include <string.h>
#include <math.h>
#define MAXN 1000000
#define INF 9999999
int valid[MAXN+1],prime[MAXN+1];
int mp[601][601],vertexs[601];
int dist[601],visited[601];
int getMin(int x,int y)
{
return x<y?x:y;
}
int Scan()
{
char ch;
int ret=0;
while((ch=getchar())<'0'||ch>'9');
while(ch>='0'&&ch<='9')
{
ret=ret*10+(ch-'0');
ch=getchar();
}
return ret;
}
void getPrime()//素数筛选O(N)
{
int i,j,tot=0;
memset(valid,1,sizeof(valid));//valid[i]=1是素数
for(i=2;i<=MAXN;++i)
{
if(valid[i])
{
tot++;
prime[tot]=i;
}
for(j=1;((j<=tot)&&(i*prime[j]<=MAXN));++j)
{
valid[i*prime[j]]=0;
if(i%prime[j]==0)
break;
}
}
valid[0]=0;
valid[1]=0;//0,1不是素数
}
int prim(int n)
{
int i,j,min,u,flag,sum=0;
for(i=0;i<n;++i)
{
dist[i]=mp[0][i];
visited[i]=0;
}
visited[0]=1;
dist[0]=0;
for(i=1;i<n;++i)
{
min=INF;
u=i;
for(j=0;j<n;++j)
{
if(!visited[j]&&dist[j]<min)
{
min=dist[j];
u=j;
}
}
if(min==INF)
break;
visited[u]=1;
sum+=dist[u];
for(j=0;j<n;++j)
{
if(!visited[j]&&dist[j]>mp[u][j])
dist[j]=mp[u][j];
}
}
flag=1;
for(i=0;i<n;++i)
{//判断是否是一棵树
if(visited[i]==0)
{
flag=0;
break;
}
}
if(flag)
return sum;
else
return -1;
}
int main()
{
int test,i,j,n,temp,tp;
getPrime();
scanf("%d",&test);
while(test--)
{
scanf("%d",&n);
for(i=0;i<n;++i)
vertexs[i]=Scan();
//scanf("%d",&vertexs[i]);
for(i=0;i<n;++i)
{
for(j=i+1;j<n;++j)
{
temp=vertexs[i]+vertexs[j];
if(valid[vertexs[i]]||valid[vertexs[j]]||valid[temp])
{
tp=abs(vertexs[i]-vertexs[j]);
temp=getMin(vertexs[i],getMin(vertexs[j],tp));
mp[i][j]=temp;
mp[j][i]=temp;
}
else
{
mp[i][j]=INF;
mp[j][i]=INF;
}
}
}
printf("%d\n",prim(n));
}
return 0;
}