压入重标记(预流推进)

#include <stdio.h> 
#include <string.h> 

const int max = 54 ; 
const long MAX = 200000000 ; 

int N, M, R ; 
long map[max][max] ;    //权值 
int src, dis ;                      //源点和汇点 

long star[max][3] ; 

long ef[max] ;      //余流 
int height[max] ;   //高度 

long sum ;          //最大流,即最小截值 

void Init(void) 
{ 
//  freopen("starwar.txt", "r", stdin); 

    int loop ; 
    int x , y ; 

    memset(map, 0, sizeof(map)) ; 

    scanf("%d %d %d", &N, &M, &R) ; 

    dis = N + 1 ; 

    for ( loop = 1; loop <= N; loop++ ) 
    { 
        scanf("%d %d %d",  
            &star[loop][0], &star[loop][1], &star[loop][2]) ; 
    } 
     
    for ( loop = 1; loop <= M; loop++ ) 
    { 
        scanf("%d %d", &x, &y); 
        map[x][y] = map[y][x] = 
            ( (star[x][0] - star[y][0]) * (star[x][0] - star[y][0]) 
            + (star[x][1] - star[y][1]) * (star[x][1] - star[y][1]) 
            + (star[x][2] - star[y][2]) * (star[x][2] - star[y][2]) ) ; 
    } 

    for ( loop = 1; loop <= N; loop++ ) 
    { 
        if ( (star[loop][0] * star[loop][0] + star[loop][1] * star[loop][1] 
            + star[loop][2] * star[loop][2]) > (R * R) ) 
        { 
            map[loop][dis] = MAX ; 
        } 
    } 

    src = 0 ; 
    for ( loop = 0; loop <= N + 1; loop++ ) 
    { 
        height[loop] = 0 ; 
    } 
    ef[src] = MAX ; 
    ef[dis] = -MAX ; 

    height[src] = N + 1 ; 

    sum = 0 ; 
} 

void PushRelabel(void) 
{ 
    long queue[max] , head , tail ; 
    queue[0] = src ; 
    head = 0 ; 
    tail = 1 ; 

    long u , v , p ; 
    int i ; 

    while( head != tail ) 
    { 
        u = queue[head++] ; 

        if ( head == max ) 
        { 
            head = 0 ; 
        } 

        for ( i = 0 ; i <= N + 1 ; i++ ) 
        { 
            v = i ; 
             
            /* 
            *   压入操作 
            */ 
            p = (map[u][v] < ef[u] ? map[u][v] : ef[u]) ; 

            if ( (p > 0) && (u == src || height[u] == height[v] + 1) ) 
            { 
                map[u][v] -= p ; 
                map[v][u] += p ; 

                if ( v == dis ) 
                { 
                    sum += p ; 
                } 

                ef[u] -= p ; 
                ef[v] += p ; 

                if ( v != src && v != dis ) 
                { 
                    queue[tail++] = v ; 

                    if ( tail == max ) 
                    { 
                        tail = 0 ; 
                    } 
                } 
            } 
        } 

        /* 
        *   重标记 
        */ 
        if ( u != src && u != dis && ef[u] > 0 ) 
        { 
            height[u]++; 
            queue[tail++] = u ; 

            if ( tail == max ) 
            { 
                tail = 0 ; 
            } 
        } 
    } 
} 

int main(void) 
{ 
    Init(); 
    PushRelabel(); 

    printf("%ld/n", sum) ; 

    return 0; 
}


转载于 http://blog.csdn.net/gzwzm/article/details/2873087
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值