poj 3625 Building Roads 最小生成树(prime或kruskal+并查集)(算法归纳)

Time Limit:1000MS Memory Limit:65536KB 64bit IO Format:%I64d & %I64u

Description

Farmer John had just acquired several new farms! He wants to connect the farms with roads so that he can travel from any farm to any other farm via a sequence of roads; roads already connect some of the farms.

Each of the N (1 ≤ N ≤ 1,000) farms (conveniently numbered 1..N) is represented by a position (Xi, Yi) on the plane (0 ≤ Xi ≤ 1,000,000; 0 ≤ Yi ≤ 1,000,000). Given the preexisting M roads (1 ≤ M ≤ 1,000) as pairs of connected farms, help Farmer John determine the smallest length of additional roads he must build to connect all his farms.

Input

* Line 1: Two space-separated integers: N and M

* Lines 2..N+1: Two space-separated integers: Xi and Yi

* Lines N+2..N+M+2: Two space-separated integers: i and j, indicating that there is already a road connecting the farm i and farm j.

Output

* Line 1: Smallest length of additional roads required to connect all farms, printed without rounding to two decimal places. Be sure to calculate distances as 64-bit floating point numbers.

Sample Input

4 1

1 1

3 1

2 3

4 3

1 4

Sample Output

4.00

意思很简单:就是给你n.m……n个点的坐标,和m条已经连好了的路线,求最小的生成树,即使每个点都直接或间接的相连。输出生成树的连接的边的长度和。。。

很裸的一道最小生成树的问题。。。

但这里。想对最小生成树的用法归纳下。。。

最小生成树大体上有两种常用的算法。。prime和kruskal算法。两种算法都得区别在于一个对点,一个对边。并没有什么优劣之分,,prime的复杂度与点有关,而kruskal的复杂度与边有关。

kruskal实质上是一种贪心的思想,,它用到了并查集和排序。。首先记录下每条边的两节点及两点之间的长度,(这里用结构体),然后以边排序,从小到大。。从最小的边取出来。如果两节点父节点不同,则加入到最小生成树的边里。合并两点的父节点。一直到最后。。这里对没条边排序再枚举,必然在时间上与边的数量有关。

poj3625:吧边的长度的开方放到已知是生成树的边里去算。。。刚好踩着时间过了。。。1000ms

(这个题的点较多。。没两个点都得计算出距离。。二最小生成树只有n-1条边。。这样可以节约不少时间)

#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
#include<map>
#include<stack>
#pragma comment(linker,"/STACK:102400000,102400000")
#define pi acos(-1.0)
#define EPS 1e-6
#define INF (1<<24)
#define mod 1000000007
using namespace std;
int father[1005];
int n,m;
int pp;   //±?êy
struct Point{
    int x,y;
}point[1005];
struct Lu{
    int x,y;
    double dis;
}lu[1000005];

bool cmp(struct Lu a,struct Lu b)
{
    return a.dis-b.dis<EPS;
}
int findfather(int x)
{
    if(x!=father[x])
        father[x]=findfather(father[x]);
    return father[x];
}
void Uion(int x,int y)
{
    int a=findfather(x);
    int b=findfather(y);
    father[a]=b;
}
bool same(int x,int y)
{
    if(findfather(x)==findfather(y)) return true;
    return false;
}
double kruskal()
{
    int i;
    int v=0;
    double res=0.0;
    for(i=0;i<pp;i++)
    {
        if(same(lu[i].x,lu[i].y)==false)
        {
            Uion(lu[i].x,lu[i].y);
            res+=sqrt((double)lu[i].dis);
            v++;
        }
        if(v==n-1-m) break;
    }
    return res;
}
int main()
{
    while(scanf("%d %d",&n,&m)!=EOF)
    {
        int i,j;
        for(i=1;i<=n;i++)
        {
            scanf("%d %d",&point[i].x,&point[i].y);
        }
        pp=0;
        for(i=1;i<=n;i++)
        {
            for(j=i+1;j<=n;j++)
            {
                lu[pp].x=i;
                lu[pp].y=j;
                double ff=(double)(point[i].x-point[j].x)*(point[i].x-point[j].x)+(double)(point[i].y-point[j].y)*(point[i].y-point[j].y);
                lu[pp].dis=ff;
                pp++;
            }
        }
        sort(lu,lu+pp,cmp);
        for(i=0;i<=n;i++) father[i]=i;
        for(i=1;i<=m;i++)
        {
            int a,b;
            scanf("%d %d",&a,&b);
            Uion(a,b);
        }
        printf("%.2f\n",kruskal());
    }
    return 0;
}

prime算法:是用的是邻接矩阵,,没有边的两点职位INF(极大值),也是从举着里去数,不断维护边,然后跟新记录某点到其他点的最小权值和。。。求最小生成树的prime和求最短路的dijkstra和相似

http://blog.csdn.net/xtulollipop/article/details/47728647

写法上也很相似,因此两算法可以一起学习了。。。

还是也是上边的题:

用prime又写了一下。。79ms。。。好吧。。完胜。。(对于给定点求最小生成树的类型的题,给了边的话。。两种算法应该都没有什么差别)。。

#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
#include<map>
#include<stack>
#pragma comment(linker,"/STACK:102400000,102400000")
#define pi acos(-1.0)
#define EPS 1e-6
#define mod 1000000007
#define INF 0x7fffffff
#define inf 0x3f3f3f3f
#define Inf 1e7
typedef long long LL;
using namespace std;
double cost[1005][1005]; //边a,b的权值。
double mincost[1005];   //x点到其他点的最下权值
bool used[1005];        //点是否被用过
int n,m;
struct Point{
    int x,y;
}point[1005];
double prime()
{
    for(int i=1;i<=n;i++) mincost[i]=1e7;
    memset(used,false,sizeof(used));
    mincost[1]=0.0;
    double res=0.0;
    while(true)
    {
        int v=-1;
        for(int i=1;i<=n;i++)
        {
            if(!used[i]&&(v==-1||mincost[i]<mincost[v])) v=i;
        }
        if(v==-1) break;
        used[v]=true;
        res+=mincost[v];
        for(int i=1;i<=n;i++)
        {
            mincost[i]=min(mincost[i],cost[v][i]);
        }
    }
    return res;
}
int main()
{
    while(scanf("%d %d",&n,&m)!=EOF)
    {
        int i,j;
        for(i=1;i<=n;i++)
        {
            scanf("%d %d",&point[i].x,&point[i].y);
            for(int j = 1; j <= n; ++j) cost[i][j] = INF;
        }
        for(i=1;i<=n;i++)
        {
            cost[i][i]=0.0;
            for(j=i+1;j<=n;j++)
            {
                double ff=(double)(point[i].x-point[j].x)*(point[i].x-point[j].x)+(double)(point[i].y-point[j].y)*(point[i].y-point[j].y);
                ff=sqrt((double)ff);
                if(cost[i][j]>ff) cost[i][j]=cost[j][i]=ff;
            }
        }

        for(i=1;i<=m;i++)
        {
            int a,b;
            scanf("%d %d",&a,&b);
            cost[a][b]=cost[b][a]=0.0;
        }
        printf("%.2f\n",prime());
    }
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-07 10:44:22

poj 3625 Building Roads 最小生成树(prime或kruskal+并查集)(算法归纳)的相关文章

poj 3625 Building Roads

题目连接 http://poj.org/problem?id=3625 Building Roads Description Farmer John had just acquired several new farms! He wants to connect the farms with roads so that he can travel from any farm to any other farm via a sequence of roads; roads already conn

HDU 1815, POJ 2749 Building roads(2-sat)

HDU 1815, POJ 2749 Building roads 题目链接HDU 题目链接POJ 题意: 有n个牛棚, 还有两个中转站S1和S2, S1和S2用一条路连接起来. 为了使得任意牛棚两个都可以有道路联通,现在要让每个牛棚都连接一条路到S1或者S2. 有a对牛棚互相有仇恨,所以不能让他们的路连接到同一个中转站.还有b对牛棚互相喜欢,所以他们的路必须连到同一个中专站. 道路的长度是两点的曼哈顿距离. 问最小的任意两牛棚间的距离中的最大值是多少? 思路:二分距离,考虑每两个牛棚之间4种连

poj 2749 Building roads (二分+拆点+2-sat)

Building roads Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 6229   Accepted: 2093 Description Farmer John's farm has N barns, and there are some cows that live in each barn. The cows like to drop around, so John wants to build some ro

SDUT 2933-人活着系列之Streetlights(最小生成树Kruskal+并查集实现)

人活着系列之Streetlights Time Limit: 1000ms   Memory limit: 65536K  有疑问?点这里^_^ 题目描述 人活着如果是为了家庭,亲情----可以说是在这个世界上最温暖人心的,也是最让人放不下的,也是我在思索这个问题最说服自己接受的答案.对,也许活着是一种责任,为了繁殖下一代,为了孝敬父母,男人要养家糊口,女人要生儿育女,就这样循环的过下去,但最终呢?还是劳苦愁烦,转眼成空呀! 为了响应政府节约能源的政策,某市要对路灯进行改革,已知该市有n个城镇,

poj 2492 a bug&#39;s life 简单种类并查集

题意大致为找同性恋的虫子.... 这个比食物链要简单些.思路完全一致,利用取余操作实现关系之间的递推. 个人感觉利用向量,模和投影可能可以实现具有更加复杂关系的并查集. 1 #include<cstdio> 2 using namespace std; 3 const int MAXN=50010; 4 int fa[MAXN]; 5 int rel[MAXN]; // 0代表同类,1代表吃fa[i],2代表被吃 6 void _set(int n) 7 { 8 for(int i=1;i&l

POJ 1984 Navigation Nightmare 二维带权并查集

题目来源:POJ 1984 Navigation Nightmare 题意:给你一颗树 k次询问 求2点之间的曼哈顿距离 并且要在只有开始k条边的情况下 思路:按照方向 我是以左上角为根 左上角为原点 dx[i]为i点距离根的x坐标 dy[]是y坐标 这两个可以通过路径压缩求出 只不过是二维而已 #include <cstdio> #include <cstdlib> #include <cstring> using namespace std; const int m

POJ 2492 || HDU 1829:A Bug&#39;s Life(并查集)

传送门: POJ:点击打开链接 HDU:点击打开链接 A Bug's Life Time Limit: 10000MS   Memory Limit: 65536K Total Submissions: 27624   Accepted: 8979 Description Background Professor Hopper is researching the sexual behavior of a rare species of bugs. He assumes that they fe

POJ 2492 A Bug&#39;s Life (带权并查集 &amp;&amp; 向量偏移)

题意 : 给你 n 只虫且性别只有公母, 接下来给出 m 个关系, 这 m 个关系中都是代表这两只虫能够交配, 就是默认异性, 问你在给出的关系中有没有与异性交配这一事实相反的, 即同性之间给出了交配关系. 分析 : 本题雷同POJ 1182 食物链, 如果会了那一题, 那现在这题便简单多了, 建议先了解食物链的偏移向量做法.这里也是使用向量的思考方式来进行relation的变化, 这里我令 relation = 0为同性, relation = 1为异性, 接下来的步骤就和食物链的雷同了. 优

POJ 1703 Find them, Catch them(数据结构-并查集)

Find them, Catch them Description The police office in Tadu City decides to say ends to the chaos, as launch actions to root up the TWO gangs in the city, Gang Dragon and Gang Snake. However, the police first needs to identify which gang a criminal b