题目大意:
给定村庄的数量,和一个矩阵表示每个村庄到对应村庄的距离,矩阵主对角线上均为1
在给定一个数目Q,输入Q行之间已经有通道的a,b
计算还要至少修建多少长度的轨道
这道题目用Kruscal方法进行计算,先将已有路径记为0,再进行所有路径长度的排序(只计算一个下三角或一个上三角,还把主对角线去掉的那种),通过并查集相交的方法,来判断二者是否属于同一个连通分量,由小到大不断找到你选取的路径,将其加起来即可
代码如下:
1 #include <iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 #define N 105 7 8 int mat[N][N]; 9 int visit[N],fa[N]; 10 struct Path{ 11 int x,y,d; 12 bool operator<(const Path &m) const{ 13 return d<m.d; 14 } 15 }path[10010]; 16 17 int getHead(int x) 18 { 19 int a=x; 20 while(fa[x]!=x) x=fa[x]; 21 fa[a]=x; 22 return x; 23 } 24 25 bool Union(int x,int y) 26 { 27 int fa_x=getHead(x); 28 int fa_y=getHead(y); 29 if(fa_x==fa_y) return false; 30 else{ 31 fa[fa_x]=fa_y; 32 return true; 33 } 34 } 35 void swap(int &a,int &b) 36 { 37 if(a<b){ 38 int temp=a; 39 a=b; 40 b=temp; 41 } 42 } 43 44 int main() 45 { 46 int n,Q,a,b,k,ans; 47 while(scanf("%d",&n)!=EOF){ 48 for(int i=1;i<N;i++) fa[i]=i; 49 memset(visit,0,sizeof(visit)); 50 k=1,ans=0; 51 for(int i=1;i<=n;i++) 52 for(int j=1;j<=n;j++) cin>>mat[i][j]; 53 for(int i=1;i<=n;i++){ 54 for(int j=1;j<i;j++) path[k].x=i,path[k].y=j,path[k++].d=mat[i][j]; 55 } 56 57 cin>>Q; 58 for(int i=1;i<=Q;i++){ 59 cin>>a>>b; 60 swap(a,b); 61 path[(a-1)*(a-2)/2+b].d=0; 62 /*if(!visit[a]) visit[a]=1,count++; 63 if(!visit[b]) visit[b]=1,count++;*/ 64 } 65 66 sort(path+1,path+k); 67 68 /*for(int i=1;i<k;i++) cout<<path[i].d<<endl; 69 cout<<"count"<<count<<endl;*/ 70 int count=0; 71 for(int i=0;i<k;i++){ 72 if(Union(path[i].x,path[i].y)) ans+=path[i].d,count++; 73 if(count==n-1) break;//当然这一步是为了做一个优化,让它可以提前跳出循环, 74 //其实不跳出循环让它一直循环结束也是成立的,只是在找到n-1条边之后, 75 //Union函数得到的判断均为false因为n个点都进入了同一个集合内 76 } 77 cout<<ans<<endl; 78 } 79 return 0; 80 }
我还在坚持,我还未达到我所想,梦~~一直在