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 }