标签:
题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=2682
题目大意:
有N个城市,每个城市有一个幸福值,如果两个城市A、B的幸福值分别为VA、VB,如果VA是
素数,或者VB是素数,又或者VA+VB是素数,则城市A和B就能连接一条路,建路的所用花费
为Min(Min(VA , VB),|VA-VB|)。
问:现在想要建几条路,使得能够连接所有的城市,所需要建设的最少路程和是多少?
思路:
就是求最小生成树,先用素数筛选法将素数打表,然后根据题意建边。最后就是用Prim模板求
最小生成树就行了。
AC代码:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
const int MAXN = 660;
const int INF = 0xffffff0;
int vis[MAXN],low[MAXN],Map[MAXN][MAXN],A[MAXN];
int prim(int n)
{
int pos,Min,result = 0;
memset(vis,0,sizeof(vis));
vis[1] = 1;
pos = 1;
for(int i = 1; i <= n; i++)
if(i != pos)
low[i] = Map[pos][i];
for(int i = 1; i < n; i++)
{
Min = INF;
for(int j = 1; j <= n; j++)
{
if(vis[j]==0 && Min > low[j])
{
Min = low[j];
pos = j;
}
}
result += Min;
vis[pos] = 1;
for(int j = 1; j <= n; j++)
{
if(vis[j]==0 && low[j] > Map[pos][j])
{
low[j] = Map[pos][j];
}
}
}
return result;
}
bool Prime[1000100];
void IsPrime()
{
for(int i = 2; i <= 1000000; ++i)
Prime[i] = true;
for(int i = 2; i <= 1000000; ++i)
{
if(Prime[i])
{
for(int j = i+i; j <= 1000000; j += i)
Prime[j] = false;
}
}
}
int father[MAXN];
int find(int x)
{
if(x == father[x])
return father[x];
else
return father[x] = find(father[x]);
}
int main()
{
int T,N;
scanf("%d",&T);
IsPrime();
while(T--)
{
scanf("%d",&N);
for(int i = 1; i <= N; ++i)
for(int j = 1; j <= N; ++j)
Map[i][j] = INF;
for(int i = 1; i <= N; ++i)
scanf("%d",&A[i]);
for(int i = 1; i <= N; ++i)
father[i] = i;
for(int i = 1; i <= N; ++i)
{
for(int j = i+1; j <= N; ++j)
{
if(Prime[A[i]] || Prime[A[j]] || Prime[A[i]+A[j]])
{
int x = find(i);
int y = find(j);
if(x != y)
father[x] = y;
Map[i][j] = Map[j][i] = min(min(A[i],A[j]),abs(A[i]-A[j]));
}
}
}
int flag = 1;
for(int i = 1; i <= N; ++i)
{
if(find(i) != find(1))
flag = 0;
}
if(flag)
printf("%d\n",prim(N));
else
printf("-1\n");
}
return 0;
}标签:
原文地址:http://blog.csdn.net/lianai911/article/details/44957465