poj1797 Heavy Transportation 最大生成树

Heavy Transportation

题意:Hugo Heavy要从城市1到城市N运送货物,有M条道路,每条道路都有它的最大载重量,问从城市1到城市N运送最多的重量是多少。

其实题意很简单,就是找一条1-->N的路径,在不超过每条路径的最大载重量的情况下,使得运送的货物最多。

分析:其实就是找一条带权路径,使得路径上最小的权值最大化,只要求一次最大生成树即可,本也没啥复杂的算法,不过这题的解题思路让我对最小生成树有了更深的理解,在这里我讲一下我对prim算法的理解。

prim算法:

1。设有一集合S,首先,将起点s(最后就成了最小生成树的根节点)放入集合,则S = {s}

2。找到距离集合S最近的一点u,加入S集合

3。通过点u,更新其余未进入集合S的点到集合S的距离

4。如果集合S外没有点了,结束,否则转到步骤2

其实整个过程中就是在找到一个距离起点集合S路径最小的点,加入进来,然后不断更新,这就像在建一棵连通树,在保证连通的情况下,不断的加入新的叶子节点,由于每次加入的边权最小,所以最后建成的就是一棵最小生成树,它能保证起点到任意一点的路径上最小的权值最小化;同理,最大生成树就是在加点的时候找权值最大的加入就行了。

 

然后看这道题:找到一条1-->N的路径,就保证连通,最后要求最小权值最大化,就是要求路径中每条边权中的最小者最大,那么就可以用最大生成树的方法,不断地将最大权值的边加入,遇到终点N就结束,这样就不会再找到一条可以更换当前路径的更好的路径了。

 

复制代码
    
    
1 /* 最大生成树 */ 2 #include < stdio.h > 3 #include < string .h > 4   #define NN 1004 5   #define INF 0x3fffffff 6   int map[NN][NN]; 7 int dis[NN]; 8 int mark[NN]; 9 int N, M; 10 11 void prim( int sta){ 12 int i; 13 for (i = 1 ; i <= N; i ++ ){ 14 dis[i] = map[sta][i]; 15 mark[i] = 0 ; 16 } 17 dis[sta] = 0 ; 18 mark[sta] = 1 ; 19 20 int num = N - 1 ; 21 22 int ans = INF; 23 while (num -- ){ 24 int max = - 2 ; 25 int key = 0 ; 26 for (i = 1 ; i <= N; i ++ ){ 27 if ( ! mark[i] && dis[i] > max){ 28 max = dis[i]; 29 key = i; 30 } 31 } 32 if (max < ans) ans = max; 33 if (key == N) break ; 34 mark[key] = 1 ; 35 for (i = 1 ; i <= N; i ++ ){ 36 if ( ! mark[i] && dis[i] < map[key][i]){ 37 dis[i] = map[key][i]; 38 } 39 } 40 } 41 printf( " %d\n " , ans); 42 } 43 int main() 44 { 45 int T, ca, a, b, c; 46 scanf( " %d " , & T); 47 for (ca = 1 ; ca <= T; ca ++ ){ 48 scanf( " %d%d " , & N, & M); 49 /* for (i = 1; i <= N; i++){ 50 for (j = 1; j <= N; j++){ 51 map[i][j] = -1; 52 } 53 } */ 54 55 memset(map, - 1 , sizeof (map)); 56 57 while (M -- ){ 58 scanf( " %d%d%d " , & a, & b, & c); 59 map[a][b] = map[b][a] = c; 60 } 61 62 printf( " Scenario #%d:\n " , ca); 63 prim( 1 );puts( "" ); 64 } 65 return 0 ; 66 } 67
复制代码
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值