HDU2724 Tree【最小生成树】

题目链接:

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;
}
时间: 2024-10-16 08:28:26

HDU2724 Tree【最小生成树】的相关文章

HDU 4786 Fibonacci Tree 最小生成树变形

思路: 这题比赛的时候想了好久,最后队友机智的想到了. 不过那时不是我敲的,现在敲的1A. 想好就容易了. 直接把1或者0当做边的权值,然后按边从小到大排序,然后算最小生成用到了几条白边,然后再按边从大到小排序,然后再算白边用了几条.然后最小和最大需要用到的白边都算出来了.如果在这最小最大区间中存在那个啥数列的话就是Yes,否则就是No. 为什么在这区间里面就是对的呢?刚开始我也想了好久,然后发现,因为白边权值是1,然后黑边是0,然后假设用到白边最小的是6,最大的是10,那么,我们可以用黑边去替

{POJ}{3925}{Minimal Ratio Tree}{最小生成树}

题意:给定完全无向图,求其中m个子节点,要求Sum(edge)/Sum(node)最小. 思路:由于N很小,枚举所有可能的子节点可能情况,然后求MST,memset()在POJ里面需要memory头文件. #include <iostream> #include <vector> #include <map> #include <cmath> #include <memory> #include <algorithm> #includ

HDOJ 2682 Tree(最小生成树prim算法)

Tree Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1954    Accepted Submission(s): 573 Problem Description There are N (2<=N<=600) cities,each has a value of happiness,we consider two cities

hdoj 2682 Tree(最小生成树)

Tree http://acm.hdu.edu.cn/showproblem.php?pid=2682 Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1855    Accepted Submission(s): 544 Problem Description There are N (2<=N<=600) cities,each

HDU 4408 Minimum Spanning Tree 最小生成树计数

Minimum Spanning Tree Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) [Problem Description] XXX is very interested in algorithm. After learning the Prim algorithm and Kruskal algorithm of minimum spanning tree, XXX

hdu 4786 Fibonacci Tree ( 最小生成树 )

Fibonacci Tree Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2487    Accepted Submission(s): 796 Problem Description Coach Pang is interested in Fibonacci numbers while Uncle Yang wants him t

hdu 2682 Tree 最小生成树~~~~水题一枚,,用到了筛法求素数,我竟然在格式上面PE了两次!!

Tree Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1754    Accepted Submission(s): 509 Problem Description There are N (2<=N<=600) cities,each has a value of happiness,we consider two cities

[HDOJ4786]Fibonacci Tree 最小生成树

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4786 先跑一遍最小生成树,注意判断是否已全部联通(用一个记号来统计最后生成树中有多少条边).再记下最小生成树的权值和A. 再反向排序,求一遍最大生成树.记下权值和B.问题转换成求[A,B]内是否有斐波那契数存在. 1 #include <algorithm> 2 #include <iostream> 3 #include <iomanip> 4 #include <

hdu 4786 Fibonacci Tree (最小生成树扩展)

///白边优先和黑边优先做两次最小生成树 ///若有斐波那契树在这中间为yes # include <stdio.h> # include <algorithm> # include <iostream> # include <string.h> # include <math.h> using namespace std; struct node { int x; int y; int v; }; struct node a[100010];