poj 2421 Constructing Roads kruskal克鲁斯卡尔最小生成树

来源:互联网 发布:国产蓝牙耳机知乎 编辑:程序博客网 时间:2024/04/30 15:55

题意:给定n个村庄(顶点),给定各村庄之间直线距离,一个n*n的二维数组,第I行第j列的值代表顶点I到j的距离,然后是q个已经修好路的村庄,要求是修最短的路,使得所有村庄相互连通。

思路:将已经修好路的各村庄的权值变为0,求最小生成树。注意图是完全图,边数是n*n-1  /  2。

当作模板用一用吧

克鲁斯卡尔算法思想:从小到大考虑每一条边,一开始生成树为空树,如果边两端点不在生成树中,将边加入生成树中,否则不考虑当前边,直到树的条件达成

树的边与点之间的关系:e边数=n顶点数-1

#include<cstdio>#include<algorithm>#include<vector>using namespace std;const int maxn = 110;int a[maxn][maxn];int f[maxn];int n,en;struct edge{int w;int from,to;};vector<edge> e;bool cmp(edge a,edge b){return a.w<b.w;}void addedge(int from,int to,int w){edge Edge={w,from,to};e.push_back(Edge);}int Find(int x){if(f[x]==x)return x;else return f[x]=Find(f[x]);}int Kuscal(){int ans=0;for(int i=1;i<=n;i++)f[i]=i;for(int i=0;i<e.size();i++){int u=e[i].from;int v=e[i].to;int x=Find(u);int y=Find(v);if(x==y)continue;f[x]=y;ans+=e[i].w;en++;if(en==n-1)break;}return ans;}int main(){//freopen("in.txt","r",stdin);while(~scanf("%d",&n)){e.clear();//      注意! for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)scanf("%d",&a[i][j]);int q,u,v;scanf("%d",&q);en=0;while(q--){scanf("%d%d",&u,&v);if(u>v)swap(u,v);a[u][v]=0;}for(int i=1;i<=n;i++){for(int j=i+1;j<=n;j++){addedge(i,j,a[i][j]);}}sort(e.begin(),e.end(),cmp);printf("%d\n",Kuscal());}}


0 0