给你一个N个顶点的邻接矩阵形式的无向图,然后给你M个已经修好的路。问最后把所有村庄连接好的最小花费
思路:我们知道所给出的m条路已经修好即是两个村庄之间的距离被更改为0,顺便熟悉 kruskal算法 ,这里便用了。
我们使用 并查集 来表示边集合,然后记录所有的边信息 ,进行一次 sort 排序,如果不在一个集合就联立,否则继续
完整代码:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; const int maxn=100+10;//点数 const int maxm=10000+10;//边数 int pre[maxn]; struct Edge{ int u,v,w; }edge[maxm]; int top; int cnt; int ans; void addedge(int u,int v,int w){ edge[top].u=u; edge[top].v=v; edge[top++].w=w; } bool cmp(Edge a,Edge b) { return a.w<b.w; } int find(int x) { if(x!=pre[x]) return pre[x] = find(pre[x]); else return pre[x]; } bool unite(int x,int y){ int fx = find(x); int fy = find(y); if(fx!=fy) { pre[fx] = fy; cnt++; return true; } else return false; } int Kruskal(int n){ sort(edge,edge+top,cmp);//一次性把所有的边都排了 int u,v,w; for(int i=0;i<top;i++){ u=edge[i].u; v=edge[i].v; w=edge[i].w; if(unite(u,v)){ ans += w; } if(cnt==n-1) break; } if(cnt<n-1) return -1; return ans; } void init(int n){ memset(edge,0,sizeof(edge)); for(int i=0;i<=n;i++) pre[i] = i; ans = top = cnt = 0; } int main(){ int n,m,w,a,b; while(cin>>n){ init(n); top=cnt=0; for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ cin>>w; addedge(i,j,w); } } cin>>m; for(int i=0;i<m;i++){ cin>>a>>b; unite(a,b); } cout<<Kruskal(n)<<endl; } return 0; }