HDU 1102 Kruscal算法

题目大意:
给定村庄的数量,和一个矩阵表示每个村庄到对应村庄的距离,矩阵主对角线上均为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 }

你可能感兴趣的:(HDU)