Hdu 2682-Tree

Topic link:
Portal

Problem Description:
There are N (2<=N<=600) cities,each has a value of happiness,we consider two cities A and B whose value of happiness are VA and VB,if VA is a prime number,or VB is a prime number or (VA+VB) is a prime number,then they can be connected.What’s more,the cost to connecte two cities is Min(Min(VA , VB),|VA-VB|).
Now we want to connecte all the cities together,and make the cost minimal.

Input:
The first will contain a integer t,followed by t cases.
Each case begin with a integer N,then N integer Vi(0<=Vi<=1000000).

Output:
If the all cities can be connected together,output the minimal cost,otherwise output “-1”;

Sample Input:
2
5
1
2
3
4
5

4
4
4
4
4

Sample Output:
4
-1

Chinese version:
Title description:
There are N (2<=N<=600) cities, and each city has a happiness value. We consider two cities a and B. Their happiness values ​​are VA and VB. If VA is A prime number, or VB is a prime number or (VA+VB) is a prime number, then they can be connected. In addition, the cost of connecting two cities is Min(Min(VA, VB), |VA-VB|).
Now we want to connect all the cities together to minimize the cost.

Input: The
first one will contain an integer t, followed by t cases.
In each case, start with the integer N, and then N integers Vi (0<=Vi<=1000000).

Output:
If all cities can be connected together, output the minimum cost, otherwise output "-1".

Sample input:
2
5
1
2
3
4
5

4
4
4
4
4

Sample output:
4
-1

Sample diagram:
Insert picture description here
Insert picture description here

Question idea:
Investigation of minimum spanning tree algorithm. When judging prime numbers, if the conventional method is used, the submission meeting time exceeds the limit, and it is safer to use the screening method to screen out the prime numbers.

prim algorithm to solve c reference code:

#include <stdio.h>
#include <string.h>//memset()函数头文件。

#define MAX 601
#define MAX1 1000001
#define INF 0x3f3f3f3f

int t,n;
int visited[MAX];
int map[MAX][MAX];
int dist[MAX];
int h[MAX];//存储城市的幸福值。
int pri[MAX1];//值为i的数为素数,则pri[i]=0;反之为1。

/*求两数中的较小值*/
int Min(int a,int b)
{
    
    
    return a<b?a:b;
}

/*求一个数的绝对值*/
int abs(int n)
{
    
    
    if(n<0)
     n=-n;
    return n;
}

/*Prim算法求最小生成树模板*/
void Prim()
{
    
    
  memset(visited,0,sizeof(visited));
  
  int i,j,sum=0;
  for(i=1;i<=n;i++)
   dist[i]=map[1][i];
  
  visited[1]=1;
  
  for(i=1;i<n;i++)
  {
    
    
      int min=INF,pos=-1;
      for(j=1;j<=n;j++)
      {
    
    
          if(visited[j]==0&&dist[j]<min)
          {
    
    
              min=dist[j];
              pos=j;
          }
      }
    
    if(pos==-1)
     break;
    else
    {
    
    
        sum+=min;
        visited[pos]=1;
    }
    
    for(j=1;j<=n;j++)
    {
    
    
        if(visited[j]==0&&dist[j]>map[pos][j])
         dist[j]=map[pos][j];
    }
  }
  
  int flag=0;
  for(i=1;i<=n;i++)
  {
    
    
      if(visited[i]==0)
      {
    
    
        flag=1;
        break;
      }
  }
  
  if(flag==0)
   printf("%d\n",sum);
  else
   printf("-1\n");
}
     
int main()
{
    
    
    int i,j,temp;
    
    /*筛选法求素数,0-是素数,1-非素数。*/
    memset(pri,0,sizeof(pri));
    pri[0]=1;
    pri[1]=1;
    for(i=2;i<MAX1;i++)
    {
    
    
     if(pri[i]==0)
     {
    
    
     	for(j=2;j<MAX1;j++)
       {
    
    
         temp=i*j;
         if(temp>MAX1)
          break;
         pri[temp]=1;
       }    
	 }
    } 
    
    scanf("%d",&t);
    while(t--)
    {
    
    
        memset(map,INF,sizeof(map));
        for(i=1;i<=n;i++)
         map[i][i]=0;
        
        scanf("%d",&n);
        for(i=1;i<=n;i++)
         scanf("%d",&h[i]);
        
        for(i=1;i<=n;i++)
        {
    
    
            for(j=1;j<=n;j++)
            {
    
    
                if(pri[h[i]]==0||pri[h[j]]==0||pri[h[i]+h[j]]==0)
                 map[i][j]=map[j][i]=Min(Min(h[i],h[j]),abs(h[i]-h[j]));
            }
        } 
        
        Prim();
    }
    return 0;
}

Kruskal algorithm to solve c reference code:

#include <stdio.h>
#include <stdlib.h>//qsort()函数头文件。
#include <string.h>

#define MAX 601
#define MAX1 1000001 

int n,t;
int parent[MAX];
int h[MAX];
int pri[MAX1];

typedef struct{
    
    
	int v1;
	int v2;
	int w;
}M,*m;

M map[179701];//无向完全图最多有n*(n-1)/2条边,600*599/2=179700。

/*求两数中的较小值*/
int Min(int a,int b)
{
    
    
	return a<b?a:b;
}

/*求一个数的绝对值*/
int abs(int n)
{
    
    
	if(n<0)
	 n=-n;
	return n;
}

/*比较函数*/
int cmp(const void *a,const void *b)
{
    
    
	m pa=(m)a;
	m pb=(m)b;
	int num1=pa->w;
	int num2=pb->w;
	return num1-num2;
}

/*并查集初始化操作*/
void init()
{
    
    
	int i;
	for(i=0;i<n;i++)
	 parent[i]=i;
}

/*寻找根节点操作*/
int find(int x)
{
    
    
	if(x==parent[x])
	 return x;
	else
	 return parent[x]=find(parent[x]);
}

/*kruskal算法*/
void kruskal(int m)
{
    
    
	int i,sum=0;
	for(i=0;i<m;i++)
	{
    
    
		int A=find(map[i].v1);
		int B=find(map[i].v2); 
		if(A!=B)
		{
    
    
			parent[A]=B;
			sum+=map[i].w;
		} 
	}
	
	int count=0;
	for(i=0;i<n;i++)
	{
    
    
		if(parent[i]==i)
		 count++;
	}
	
	if(count==1)//如果只有一个根节点,说明所有城市都连通。
	 printf("%d\n",sum);
	else
	 printf("-1\n");
}

int main()
{
    
    
	int i,j,k,temp;
	
	/*筛选法判断素数*/
	memset(pri,0,sizeof(pri));
	pri[0]=1;
	pri[1]=1;
	for(i=2;i<MAX1;i++)
	{
    
    
		if(pri[i]==0)
		{
    
    
			for(j=2;j<MAX1;j++)
			{
    
    
				temp=i*j;
				if(temp>MAX1)
				 break;
				pri[temp]=1;
			}
		}
	}
	
	scanf("%d",&t);
	while(t--)
	{
    
    
		scanf("%d",&n);
		for(i=0;i<n;i++)
		 scanf("%d",&h[i]);
		
		for(i=0,k=0;i<n;i++)
		{
    
    
			for(j=0;j<n;j++)
			{
    
    
				if(pri[h[i]]==0||pri[h[j]]==0||pri[h[i]+h[j]]==0)
				{
    
    
					map[k].v1=i;
					map[k].v2=j;
					map[k++].w=Min(Min(h[i],h[j]),abs(h[i]-h[j]));
				}
			}
		}
		
		qsort(map,k,sizeof(map[0]),cmp);
		
		init();
		kruskal(k);
	}
	return 0;
} 

Reference:
Portal

Guess you like

Origin blog.csdn.net/qq_46139801/article/details/114676254