poj 3436 ACM Computer Factory(最大流基础,拆点)

题意:
产品有p个部分。
有n台机器, 用生产速率,接受列表,输出列表描述。
连接这n台机器,使得总生产速率最大。
思路:
把每台机器拆成,入点和出点,容量为生产速率。
然后添加超级源点和汇点。

用dinic算法做的第一题
其实对dinic分层的正确性还是没有理解。。

const int inf = INT_MAX/2;
const int Maxn = 100000;
const int MaxV = 200;
struct Edge {
    int to, cap, rev;
};

vector<Edge> G[MaxV+5];
int level[MaxV+5], iter[MaxV+5]; // 距离标号,当前边
int qi[MaxV+5], si[MaxV+5][11], di[MaxV+5][11], p, n;

// 在残量网络里面加边
void add_edge(int from, int to, int cap) {
    G[from].push_back( (Edge){to, cap, G[to].size()} );
    G[to].push_back( (Edge){from, 0, G[from].size()-1} );
}

// bfs 构建层次
void bfs(int s) {
    memset(level, -1, sizeof(level));
    level[s] = 0;
    queue<int> q;
    q.push(s);
    while (!q.empty()) {
        int u = q.front();q.pop();
        int sz = G[u].size();
        for (int i=0;i<sz;++i) {
            Edge &e = G[u][i];
            if (e.cap > 0 && level[e.to] < 0) {
                level[e.to] = level[u] + 1;
                q.push(e.to);
            }
        }
    }
}

int dfs(int x, int t, int f) {
    //cout << "go " << x << endl;
    if (x == t || f == 0) return f;
    int flow = 0, sz = G[x].size();
    for (int &i = iter[x]; i<sz;++i) {
        Edge &e = G[x][i];
        if (e.cap > 0 && level[x] < level[e.to]) {
            int d = dfs(e.to, t, min (f, e.cap));
            if (d > 0) {
                e.cap -= d;
                G[e.to][e.rev].cap += d;
                flow += d;
                f -= d;
                if (!f) break;
            }
        }
    }
    return flow;
}

int max_flow(int s, int t) {
    int flow = 0;
    for (;;) {
        bfs (s);
        if (level[t] < 0) return flow;
        memset(iter, 0, sizeof(iter));
        flow += dfs(s, t, inf);
    }
    return flow;
}

void add_ans(vector<int> &x, vector<int> &y, vector<int> &z) {
    rep(i, n+1, 2*n) {
        int sz = G[i].size();
        rep(j, 0, sz-1) {
            Edge &e = G[i][j];
            if (e.to != 2*n+1 && i - e.to != n && G[e.to][e.rev].cap > 0)
                x.push_back(i-n),
                y.push_back(e.to),
                z.push_back(G[e.to][e.rev].cap);
        }
    }
}

int main() {
#ifndef ONLINE_JUDGE
    freopen("input.in", "r", stdin);
#endif
    SPEED_UP
    while (cin >> p >> n) {
        rep(i, 0, 2*n+1) G[i].clear();
        rep(i, 1, n) {
            cin >> qi[i];
            int st = 0;
            rep(j, 0, p-1) cin >> si[i][j];
            rep(j, 0, p-1) cin >> di[i][j];
        }
        rep(i, 1, n) rep(j, 1, n) if (i != j) {
            int ok = 1;
            rep(k, 0, p-1) {
                if (si[j][k] == 2 || di[i][k] == si[j][k]) continue;
                ok = 0;
                break;
            }
            if (ok) {
                // add edge
                add_edge(i+n, j, qi[i]);
                //cout << "add edge: " << i << ' ' << j << ' ' << qi[i] << endl;
            }
        }
        // 超级源点0
        rep(i, 1, n) {
            int ok = 1;
            rep(j, 0, p-1) if (si[i][j] == 1) {ok = 0;break;}
            if (ok) add_edge(0, i, inf);
        }
        // 超级汇点2n+1
        rep(i, 1, n) {
            int ok = 1;
            rep(j, 0, p-1) if (!di[i][j]) {ok = 0;break;}
            if (ok) add_edge(i+n, 2*n+1, qi[i]);
        }
        // 一个节点拆成2个 i -> i, i+n
        rep(i, 1, n) {
            add_edge(i, i+n, qi[i]);
        }

        int _max = max_flow(0, 2*n+1);
        vector<int> x, y, z;
        add_ans(x, y, z);

        cout << _max << ' ' << x.size() << endl;
        for (int i=0;i<x.size();++i) cout << x[i] << ' ' << y[i] << ' ' << z[i] << endl;
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值