hdu 2489 Minimal Ratio Tree (DFS枚举+MST)

参考链接:http://blog.csdn.net/xingyeyongheng/article/details/9373271

     http://www.cnblogs.com/chenxiwenruo/p/3294668.html

 

 1 #include<iostream>

 2 #include<cstdio>

 3 #include<cstdlib>

 4 #include<cstring>

 5 #include<string>

 6 #include<queue>

 7 #include<algorithm>

 8 #include<map>

 9 #include<iomanip>

10 #define INF 99999999

11 using namespace std;

12 

13 const int MAX = 15 + 5;

14 int edge[MAX][MAX], dist[MAX], node[MAX];//node记录最终选的点 

15 int vale[MAX], temp[MAX], n, m;//temp记录选的m个点

16 double minratio;

17 bool mark[MAX];

18 

19 int Prim(int s){

20     int sum = 0;

21     for (int i = 1; i <= m; ++i)mark[temp[i]] = false, dist[temp[i]] = edge[s][temp[i]];

22     mark[s] = true;

23     dist[s] = 0;

24     for (int i = 1; i<m; ++i){

25         int point = s;

26         for (int j = 1; j <= m; ++j){

27             if (point == s && !mark[temp[j]])point = temp[j];

28             if (!mark[temp[j]] && dist[point]>dist[temp[j]])point = temp[j];

29         }

30         mark[point] = true;

31         sum += dist[point];

32         for (int j = 1; j <= m; ++j){

33             if (!mark[temp[j]] && edge[point][temp[j]]<dist[temp[j]])dist[temp[j]] = edge[point][temp[j]];

34         }

35     }

36     return sum;

37 }

38 /*

39 dfs枚举m个点,num代表目前选取了多少个点,k代表第num个点为k。

40 表示前num个点选自1~k,剩余的点从k+1~n中选。

41 */

42 void dfs(int u, int num){

43     if (num == m){

44         int ans = 0;

45         for (int i = 1; i <= m; ++i)ans += vale[temp[i]];

46         double sum = Prim(u)*1.0 / ans;

47         if (sum - minratio < -(1e-9)){

48             minratio = sum;

49             for (int i = 1; i <= m; ++i) node[i] = temp[i];

50         }

51         return;

52     }

53  //若剩余的点的个数(n-k)加上目前选取的个数num小于m的话,说明即使接下来n-k个点都选取,也选不足m个点,直接return

54     if (n - u + num<m)return;

55     for (int i = u + 1; i <= n; ++i){

56         temp[num + 1] = i;

57         dfs(i, num + 1);

58     }

59 }

60 

61 int main(){

62     while (cin >> n >> m, n + m){

63         minratio = INF*1.0;

64         for (int i = 1; i <= n; ++i)cin >> vale[i];

65         for (int i = 1; i <= n; ++i){

66             for (int j = 1; j <= n; ++j){

67                 cin >> edge[i][j];

68             }

69         }

70         for (int i = 1; i <= n; ++i){

71             temp[1] = i;

72             dfs(i, 1);

73         }

74         for (int i = 1; i<m; ++i)cout << node[i] << ' ';

75         cout << node[m] << endl;

76     }

77     return 0;

78 }

 

别的大牛DFS写法

 1 //调用时:dfs(1,0,0);

 2 

 3 //dep表示点的编号,cnt表示选取的点的个数,sum_pw表示目前选取了cnt个点后总的点权值

 4 void dfs(int dep, int cnt, int sum_pw) {

 5     if(cnt == m) {

 6         ...;

 7         return ;

 8     }

 9     if(dep == n + 1) return ;

10     use[dep] = true;  //选取点dep,这里use[i]=true表示选取点i,在用prim求最小生成树的时候有用

11     dfs(dep + 1, cnt + 1, sum_pw + weight[dep]);

12     use[dep] = false; //不选取点dep

13     dfs(dep + 1, cnt, sum_pw);

14 }

 

你可能感兴趣的:(tree)