HDU2724 Tree【最小生成树】

来源:互联网 发布:三国志13 知乎 编辑:程序博客网 时间:2024/09/21 09:28

题目链接:

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;}


0 0