3 1 2 1 0 1 3 2 0 2 3 4 0 3 1 2 1 0 1 3 2 0 2 3 4 1 3 1 2 1 0 1 3 2 1 2 3 4 1 0
3 1 0
解题思路
运用克鲁斯卡尔算法,也就是并查集的知识。每次都用递归找到各自最终的数据判断是否相等,若想等则表示有联系,若没联系则建立联系。在递归找最开始元素的时候有点儿问题。
错误原因
一开始是Runtime Error(ACCESS_VIOLATION),越界了。仔细看题之后才发现人家给的道路是n*(n-1)/2,还需要在定义一个变量m来当范围。
代码
#include<stdio.h> #include<algorithm> using namespace std; int city[110]; struct road { int x,y,q; }roads[5000]; int find(int a) { if(city[a]==a) return a; else return city[a]=find(city[a]); //这一步是递归找到有联系的最终那个元素。这都是通过数组的值来判断的。 } bool cmp(road a, road b) { return a.q<b.q; } int main() { int n; int o,m; int i,j,k,sum; while(scanf("%d",&n),n) { for(i=1;i<=n;i++) city[i]=i; m=n*(n-1)/2; for(i=0;i<m;i++) { scanf("%d%d%d%d",&roads[i].x,&roads[i].y,&roads[i].q,&o); if(o==1) { j=find(roads[i].x); k=find(roads[i].y); city[j]=k; //这一步是将两个地方建立联系,那建立联系就是 //在数组上赋值。 } } sort(roads,roads+m,cmp); sum=0; for(i=0;i<m;i++) { j=find(roads[i].x); k=find(roads[i].y); if(j!=k) { city[j]=k; sum+=roads[i].q; } } printf("%d\n",sum); } return 0; }