压入重标记(预流推进)

  1. #include <stdio.h>
  2. #include <string.h>
  3. const int max = 54 ;
  4. const long MAX = 200000000 ;
  5. int N, M, R ;
  6. long map[max][max] ;    //权值
  7. int src, dis ;                      //源点和汇点
  8. long star[max][3] ;
  9. long ef[max] ;      //余流
  10. int height[max] ;   //高度
  11. long sum ;          //最大流,即最小截值
  12. void Init(void)
  13. {
  14. //  freopen("starwar.txt", "r", stdin);
  15.     int loop ;
  16.     int x , y ;
  17.     memset(map, 0, sizeof(map)) ;
  18.     scanf("%d %d %d", &N, &M, &R) ;
  19.     dis = N + 1 ;
  20.     for ( loop = 1; loop <= N; loop++ )
  21.     {
  22.         scanf("%d %d %d"
  23.             &star[loop][0], &star[loop][1], &star[loop][2]) ;
  24.     }
  25.     
  26.     for ( loop = 1; loop <= M; loop++ )
  27.     {
  28.         scanf("%d %d", &x, &y);
  29.         map[x][y] = map[y][x] =
  30.             ( (star[x][0] - star[y][0]) * (star[x][0] - star[y][0])
  31.             + (star[x][1] - star[y][1]) * (star[x][1] - star[y][1])
  32.             + (star[x][2] - star[y][2]) * (star[x][2] - star[y][2]) ) ;
  33.     }
  34.     for ( loop = 1; loop <= N; loop++ )
  35.     {
  36.         if ( (star[loop][0] * star[loop][0] + star[loop][1] * star[loop][1]
  37.             + star[loop][2] * star[loop][2]) > (R * R) )
  38.         {
  39.             map[loop][dis] = MAX ;
  40.         }
  41.     }
  42.     src = 0 ;
  43.     for ( loop = 0; loop <= N + 1; loop++ )
  44.     {
  45.         height[loop] = 0 ;
  46.     }
  47.     ef[src] = MAX ;
  48.     ef[dis] = -MAX ;
  49.     height[src] = N + 1 ;
  50.     sum = 0 ;
  51. }
  52. void PushRelabel(void)
  53. {
  54.     long queue[max] , head , tail ;
  55.     queue[0] = src ;
  56.     head = 0 ;
  57.     tail = 1 ;
  58.     long u , v , p ;
  59.     int i ;
  60.     while( head != tail )
  61.     {
  62.         u = queue[head++] ;
  63.         if ( head == max )
  64.         {
  65.             head = 0 ;
  66.         }
  67.         for ( i = 0 ; i <= N + 1 ; i++ )
  68.         {
  69.             v = i ;
  70.             
  71.             /*
  72.             *   压入操作
  73.             */
  74.             p = (map[u][v] < ef[u] ? map[u][v] : ef[u]) ;
  75.             if ( (p > 0) && (u == src || height[u] == height[v] + 1) )
  76.             {
  77.                 map[u][v] -= p ;
  78.                 map[v][u] += p ;
  79.                 if ( v == dis )
  80.                 {
  81.                     sum += p ;
  82.                 }
  83.                 ef[u] -= p ;
  84.                 ef[v] += p ;
  85.                 if ( v != src && v != dis )
  86.                 {
  87.                     queue[tail++] = v ;
  88.                     if ( tail == max )
  89.                     {
  90.                         tail = 0 ;
  91.                     }
  92.                 }
  93.             }
  94.         }
  95.         /*
  96.         *   重标记
  97.         */
  98.         if ( u != src && u != dis && ef[u] > 0 )
  99.         {
  100.             height[u]++;
  101.             queue[tail++] = u ;
  102.             if ( tail == max )
  103.             {
  104.                 tail = 0 ;
  105.             }
  106.         }
  107.     }
  108. }
  109. int main(void)
  110. {
  111.     Init();
  112.     PushRelabel();
  113.     printf("%ld/n", sum) ;
  114.     return 0;
  115. }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值