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

 

 

posted @ 2013-06-05 14:41  ihge2k  阅读(255)  评论(0编辑  收藏  举报