poj 1751

来源:互联网 发布:安全知识网络 编辑:程序博客网 时间:2024/05/16 09:56
#include<cstdio>#include<cstring>#include<iostream>#include<utility>#include<string>#include<vector>#include<algorithm>#include<queue>#include<cstdlib>#include<cmath>using namespace std;const double eps=1e-8;const int M=800;struct Node{int u,v;double w;bool operator < (const Node a)const{return w<a.w;};}edge[M*M];struct point{int x,y;}p[M];int pare[M],num,n,m;int ans[M][2],cnt;void init(){for(int i=1;i<=n+2;i++){pare[i]=i;}num=cnt=0;}int find(int x){if(pare[x]!=x)pare[x]=find(pare[x]);return pare[x];}void unionedge(int x,int y){pare[find(x)]=pare[find(y)];}void build(){for(int i=1;i<=n;i++){for(int j=i+1;j<=n;j++)if(find(i)!=find(j)){edge[num].u=i;edge[num].v=j;edge[num++].w=sqrt((double)((p[i].x-p[j].x)*(p[i].x-p[j].x)+(p[i].y-p[j].y)*(p[i].y-p[j].y)));}}sort(edge,edge+num);}void kruskal(){for(int i=0;i<num;i++)if(find(edge[i].u)!=find(edge[i].v)){unionedge(edge[i].u,edge[i].v);printf("%d %d\n",edge[i].u,edge[i].v);}}int main(){scanf("%d",&n);int a,b;for(int i=1;i<=n;i++){scanf("%d%d",&p[i].x,&p[i].y);}scanf("%d",&m);init();while(m--){scanf("%d%d",&a,&b);unionedge(a,b);}build();kruskal();return 0;}


        题目意思是对一堆给定的村庄建路使得村村可达,且存在的道路不算入新建道路内。

        最小生成树问题。对于已存在道路的两个村庄,则将其加入并查集中。最后用kruskal算法跑一次即可。

 

        以下是详细代码: