POJ 1751 Highways 最小生成树

来源:互联网 发布:遥感卫星数据 英文 编辑:程序博客网 时间:2024/05/22 10:54

POJ 1751 Highways 最小生成树

  题意:给你n个村庄的坐标,然后再给你m行,每行的两个数字代表公路两端的村庄编号(1~n),问在花费最少的情况下还需建哪些路才能使所有村庄连通。

  思路:kruskal的话思路很明确,先建好边集,然后将每条已经建好的路执行合并操作,即Add(a,b);,然后再用kruskal输出一遍每次建边的两个村庄编号就OK。prim的话,没想到该怎么写,网上很多题解都是用的prim。

  疑问:之前把村庄编号从0~n-1开始记,输出时再+1,但是一直WA,没找到原因,之后换了从1~n的编号,就奇迹过了。还有一个RE的问题,就是如果main里面写成下面这样,然后把solve里的scanf("%d",&n);删掉,会报RE,

While(~scanf("%d",&n)) {    solve();}

AC代码:

////  main.cpp//  L////  Created by LucienShui on 2017/5/11.//  Copyright © 2017年 LucienShui. All rights reserved.//#include <iostream>#include <algorithm>#include <set>#include <string>#include <vector>#include <queue>#include <map>#include <iomanip>#include <cstdio>#include <cstring>#include <cmath>#include <cctype>#define memset(a,b) memset(a,b,sizeof(a))#define ull unsigned long longusing namespace std;const int maxn = 807;int m,n,pre[maxn],height[maxn],cnt;struct {    int x,y;}node[maxn];struct Edge{    int b,e;    int val;    bool operator < (const Edge x) const {        return this->val < x.val;    }}edge[maxn*maxn];int Find(int x) {//while以及附帶路徑壓縮的版本,遞歸在數據量比較大的時候可能爆    if(x==pre[x]) return x;    int p=x,q;    while(x!=pre[x]) x=pre[x];    while(p!=pre[p]) {        q=pre[p];        pre[p]=x;        p=q;    }    return x;}void Add(int i, int j) {    int x=Find(i),y=Find(j);    if(x==y) return ;    if(height[x]<height[y]) pre[x]=y;    else {        if(height[x]==height[y]) height[x]++;        pre[y]=x;    }    return ;}void kruskal() {    sort(edge,edge+cnt);    for(int i=0 ; i<cnt ; i++) {        if(Find(edge[i].b)!=Find(edge[i].e)) {            Add(edge[i].b,edge[i].e);            printf("%d %d\n",edge[i].b,edge[i].e);        }    }    return ;}inline int calc(int a, int b) {    int x = node[a].x - node[b].x,y = node[a].y - node[b].y;    return x*x+y*y;}void solve() {    scanf("%d",&n);    for(int i=1 ; i<=n ; i++) {        scanf("%d%d", &node[i].x, &node[i].y);    }    for(int i=0 ; i<=n ; i++) {        pre[i]=i,height[i]=1;    }    cnt = 0;    for(int i=1 ; i<=n ; i++) {        for(int j=i+1 ; j<=n ; j++) {            if(Find(i)!=Find(j)) {                edge[cnt].b = i;                edge[cnt].e = j;                edge[cnt++].val = calc(i,j);            }        }    }    scanf("%d",&m);    for(int i=1,a,b ; i<=m ; i++) {        scanf("%d%d",&a,&b);        if(Find(a)!=Find(b)) {            Add(a,b);        }    }    kruskal();}int main() {#ifndef ONLINE_JUDGE    freopen("in.txt", "r", stdin);#endif    solve();    return 0;}