码迷,mamicode.com
首页 > Web开发 > 详细

zoj2676 Network Wars(0-1分数规划,最大流模板)

时间:2014-11-11 16:42:48      阅读:247      评论:0      收藏:0      [点我收藏+]

标签:最小割0-1分数规划

Network Wars

07年胡伯涛的论文上的题:http://wenku.baidu.com/view/87ecda38376baf1ffc4fad25.html
代码:

#include <algorithm>
#include <cstdio>
#include <iterator>
#include <limits>
#include <vector>
#include <string.h>

const int N = 111;
const int M = 404;
const double EPS = 1e-3;

typedef std::vector<int> VI;

int signum(double x) {
    return x > EPS ? 1 : (x < -EPS ? -1 : 0);
}

template<int N, int M, class Flow>
struct Dinic {
    int n, e, first[N], cur[N], next[M], to[M], id[M], s, t;
    int pre[N], level[N], q[N], sign;
    Flow cap[M], flow;
    void add(int u, int v, Flow w, int i) {
        to[e] = v;
        cap[e] = w;
        id[e] = i;
        next[e] = first[u];
        first[u] = e++;
    }
    bool bfs(int s, int t) {
        std::fill(level+1, level + n + 1, -1);
        sign = t;
        level[t] = 0;
        int head = 0, tail = 0;
        q[tail++] = t;
        while (head != tail && level[s] == -1) {
            int u = q[head++];
            for (int it = first[u]; it != -1; it = next[it]) {
                if (cap[it ^ 1] > 0 && level[to[it]] == -1) {
                    level[to[it]] = level[u] + 1;
                    q[tail++] = to[it];
                }
            }
        }
        return level[s] != -1;
    }
    void push() {
        Flow delta = std::numeric_limits<Flow>::max();
        int u, p;
        for (u = t; u != s; u = to[p ^ 1]) {
            p = pre[u];
            delta = std::min(delta, cap[p]);
        }
        for (u = t; u != s; u = to[p ^ 1]) {
            p = pre[u];
            cap[p] -= delta;
            if (!cap[p]) {
                sign = to[p ^ 1];
            }
            cap[p ^ 1] += delta;
        }
        flow += delta;
    }
    void dfs(int u) {
        if (u == t) {
            push();
        } else {
            for (int & it = cur[u]; it != -1; it = next[it]) {
                if (cap[it] > 0 && level[u] == level[to[it]] + 1) {
                    pre[to[it]] = it;
                    dfs(to[it]);
                    if (level[sign] > level[u]) {
                        return;
                    }
                    sign = t;
                }
            }
            level[u] = -1;
        }
    }
    void init(int _n, int _s, int _t) {
        n = _n, s = _s, t = _t;
        std::fill(first + 1 , first + n + 1 , -1);
        e = 0;
    }
    Flow solve() {
        flow = 0;
        while (bfs(s, t)) {
            for (int i = 1; i <= n; ++i) {
                cur[i] = first[i];
            }
            dfs(s);
        }
        return flow;
    }
};

Dinic<N,M<<1,double> AC ;
int left[M] , right[M] , w[M] ;
int n , m , mark[M] ;

double judge ( double key ) {
    double sum = 0 ;
    memset ( mark , 0 , sizeof ( mark ) ) ;
    AC.init ( n , 1 , n ) ;
    for ( int i = 1 ; i <= m ; i ++ )
        if ( w[i] <= key ) {
            sum += w[i] - key ;
            mark[i] = 1 ;
        } else {
            AC.add ( left[i] , right[i] , w[i] - key , i ) ;
            AC.add ( right[i] , left[i] , w[i] - key , i ) ;
        }
    double add = AC.solve () ;
    sum += add ;
    return sum ;
}

void solve () {
    double l = 0 , r = (double) m * 1e7 ;
    while ( signum (r-l) > 0 ) {
        double mid = ( l + r ) / 2.0 ;
        double k = judge ( mid ) ;
        if ( signum ( k ) >= 0 ) l = mid ;
        else r = mid ;
    }
    AC.bfs ( 1 , n ) ;
    for ( int i = 0 ; i < AC.e ; i ++ ) {
        int u = AC.to[i^1] , v = AC.to[i] ;
        if ( AC.level[u] == -1 && AC.level[v] != -1 )
        mark[AC.id[i]] = 1 ;
    }
    int ans = 0 ;
    for ( int i = 1 ; i <= m ; i ++ ) if ( mark[i] ) ans ++ ;
    printf ( "%d\n" , ans ) ;
    for ( int i = 1 ; i <= m ; i ++ ) if ( mark[i] ) printf ( "%d " , i ) ;
    puts ( "" ) ;
}

int main () {
 //   freopen("network.in", "r", stdin);
 //   freopen("network.out", "w", stdout);
    int flag = 0 ;
    while ( scanf ( "%d%d" , &n , &m ) != EOF ) {
        for ( int i = 1 ; i <= m ; i ++ )
            scanf ( "%d%d%d" , &left[i] , &right[i] , &w[i] ) ;
        if ( flag ) puts ( "" ) ;
        flag = 1 ;
        solve () ;
    }
    return 0 ;
}


zoj2676 Network Wars(0-1分数规划,最大流模板)

标签:最小割0-1分数规划

原文地址:http://blog.csdn.net/no__stop/article/details/41011871

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!