hdu 2682(最小生成树)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2682

思路:一个裸的最小生成树,先打个素数表,然后就是连边了。dfs判断是否连通,连通的话就是kruskal求最小生成树了。

  1 #include<iostream>

  2 #include<cstdio>

  3 #include<cstring>

  4 #include<algorithm>

  5 #include<cmath>

  6 using namespace std;

  7 #define MAXN 666

  8 struct Edge{

  9    int u,v,w;

 10 }edge[MAXN*MAXN];

 11 bool map[MAXN][MAXN];

 12 bool prime[2222222];

 13 int parent[MAXN];

 14 bool mark[MAXN];

 15 int value[MAXN];

 16 int n,m,sum;

 17 

 18 void Initiate(){

 19    memset(prime,true,sizeof(prime));

 20    prime[0]=prime[1]=false;

 21    for(int i=2;i*i<=2222000;i++){

 22       if(prime[i]){

 23          for(int j=i*i;j<=2222000;j+=i){

 24             prime[j]=false;

 25          }

 26       }

 27    }

 28 }

 29 

 30 void dfs(int u){

 31    mark[u]=true;

 32    for(int i=1;i<=n;i++){

 33       if(map[u][i]&&!mark[i])dfs(i);

 34    }

 35 }

 36 

 37 int cmp(const Edge &p,const Edge &q){

 38    return p.w<q.w;

 39 }

 40 

 41 int Find(int x){

 42    int s;

 43    for(s=x;parent[s]>=0;s=parent[s])

 44    ;

 45    while(s!=x){

 46       int tmp=parent[x];

 47       parent[x]=s;

 48       x=tmp;

 49    }

 50    return s;

 51 }

 52 

 53 void Union(int R1,int R2){

 54    int r1=Find(R1);

 55    int r2=Find(R2);

 56    if(r1==r2)return ;

 57    if(parent[r1]<parent[r2]){

 58       parent[r1]+=parent[r2];

 59       parent[r2]=r1;

 60    }else {

 61       parent[r2]+=parent[r1];

 62       parent[r1]=r2;

 63    }

 64 }

 65 

 66 

 67 int main(){

 68  //  freopen("1.txt","r",stdin);

 69    Initiate();

 70    int _case;

 71    scanf("%d",&_case);

 72    while(_case--){

 73       scanf("%d",&n);sum=m=0;

 74       for(int i=1;i<=n;i++)scanf("%d",&value[i]);

 75       memset(mark,false,sizeof(mark));

 76       memset(map,false,sizeof(map));

 77       for(int i=1;i<=n;i++){

 78          for(int j=i+1;j<=n;j++){

 79             if(prime[value[j]]||prime[value[i]]||prime[value[i]+value[j]]){

 80                map[i][j]=map[j][i]=true;

 81                edge[m].u=i;

 82                edge[m].v=j;

 83                edge[m++].w=min(min(value[i],value[j]),abs(value[i]-value[j]));

 84             }

 85          }

 86       }

 87       dfs(1);

 88       bool flag=true;

 89       for(int i=1;i<=n;i++)if(!mark[i]){ flag=false;break; }

 90       if(!flag){ puts("-1");continue; }

 91       memset(parent,-1,sizeof(parent));

 92       sort(edge,edge+m,cmp);

 93       for(int i=0;i<m;i++){

 94          int u=Find(edge[i].u);

 95          int v=Find(edge[i].v);

 96          if(u!=v){

 97             sum+=edge[i].w;

 98             Union(u,v);

 99          }

100       }

101       printf("%d\n",sum);

102    }

103    return 0;

104 }
View Code

 

 

你可能感兴趣的:(最小生成树)