题解西电OJ (Problem 1004 -亚特兰提斯)--最小生成树

Description

  为了找寻沉睡的亚特兰提斯大陆,wm来到了大西洋上进行探险,找了半个月仍一无所获。然而在一次突袭而来的暴风雨后,wm的船莫名地驶入了一片未知的区域,发现了一个地图上未标记的岛屿,这让他感到相当惊讶,强烈的好奇心驱使他上岸看看究竟。 
船在岛屿靠岸后岛上的国王举行庆典热情地款待了他,整个岛一片喜庆。国王自称是亚特兰提斯人,而这个岛屿曾经是亚特兰提斯大陆的最高地。现在岛屿上还有N个城市,由于岛上的资源相当有限且岛上没人知道怎么合理利用资源故一直以来在城市之间都没有铺设道路,现在国王想请wm规划下道路并进行建设,国王对规划的要求如下: 
  1.所有城市必须连通,即任意两个城市都可以互相来往 
  2.国王是个娇气的人,所以他希望从任意城市走到任意另一个城市时的“舒适度”越高越好,其中两个城市间的“舒适度”定义为:两个城市间路径的每一段道路的“舒适度”的最小者,例如从A到B需要经过C城市,A->C段“舒适度”为10,C->B段“舒适度”为100,则A->B的“舒适度”为10(当然如果两个城市间有很多路径的话国王会走“舒适度”最大的路径)。现在定义K为所有两个城市间“舒适度”的最小者,而国王希望K越大越好。 
  现在岛上的资源只有R单位,国王希望wm帮他规划道路满足他的要求,在岛上资源条件的允许下输出最大的K。如果岛上的资源不够满足第1个要求,则输出-1。 
wm沉迷于岛上的玩乐,懒得去想这问题了,所以他远程求助你,帮他解决这个烦人的问题。

Input
  输入包含多组数据,EOF结束。 
  每组数据以三个整数开头,N,M,R。N(2<=N<=1000)是城市数,M(0<=M<=100000)是允许建造的道路数,R(0<=R<=100000)是岛上仅有的资源数。EOF结束。 
  接下来有M行数据,每行包括a,b(0<=a,b<N),v(0<v<=100000),c(0<=c<=100000)四个整数,表示ab城市间允许建一条双向道路,花费v单位资源,“舒适度”为c。
Output
  每组数据输出一行,岛上资源条件的允许下最大的K或-1。
Sample Input
3 3 1000
0 1 20 8
1 2 10 7
2 0 10 6
3 3 20
0 1 20 8
1 2 10 7
2 0 10 6
2 1 10
0 1 20 8
Sample Output
7
6
-1
 
问题分析:
 
其实这个题就是一个最小生成树的问题,因为题中的K,就是国王的舒适度,需要在消耗资源R以内,建成一颗树,联通所有城市
那么我的解决方案就是K的最小值为 D 时,将所有舒适度小于D的路均不考虑,生成最小生成树,是否满足资源消耗小于R,K的最小值通过二分法获得。
 
代码如下:
 
 1 #include <iostream>

 2 #include <stdlib.h>

 3 using namespace std;

 4 

 5 

 6 struct Path{

 7     int start ;

 8     int end ;

 9     int cost ;

10     int wieght ;

11 } ;

12 

13 Path path[100000] ;

14 

15 int wight[100000] ;

16 int p[1001];

17 

18 //int res ;

19 

20 int n , m , r , new_m;

21 

22 

23 

24 int find_root(int a){

25     while(a!=p[a]){

26         a = p[a] ;

27     }

28     return a;

29 }

30 

31 bool krusker(int cur_w)

32 {

33     int m_cost = 0 ;

34     int i = 0;

35     for(i = 0 ; i < n ;i++){

36         p[i] = i ;

37     }

38 

39     int x , y ;

40     int count = 0 ;

41     for(i = 0 ; i < m; i++){

42         if(path[i].wieght < cur_w){

43             continue ;

44         }

45         x = find_root(path[i].start);

46         y = find_root(path[i].end);

47         if(x!=y){            

48             m_cost += path[i].cost;

49             p[x] = y ;

50             if(m_cost > r){

51                 return false ;

52             }

53             count ++ ;

54             if(count == n-1){

55                 return true;

56             }

57         }        

58     }

59 

60     return false;

61 }

62 

63 

64 int comp1(const void *a,const void *b)

65 {

66     return (*(Path *)a).cost - (*(Path *)b).cost ;

67 }

68 

69 

70 

71 

72 int main()

73 {

74 

75     

76     while(cin >> n >> m >> r){

77 //        res = -1 ;

78         int i , j , k ;

79         int minw = 1000000 ;

80         int maxw = -1 ;

81         for(i = 0 ; i < m ; i++)

82             cin >> path[i].start >> path[i].end >> path[i].cost >> path[i].wieght ;

83         k = 0 ;

84         qsort(path,m,sizeof(Path),comp1) ;

85         int l = -1 ;

86         j = 100001;

87         while(l<j-1){

88             k = (l + j) / 2 ;

89             if(krusker(k)){

90                 l = k ;

91             }else{

92                 j = k ;

93             }

94         }

95         cout << l << endl ;

96     }

97     return 0;

98 }

 

 
 
 
 

你可能感兴趣的:(最小生成树)