zoukankan      html  css  js  c++  java
  • POJ_3436 ACM Computer Machine (网络流)

      参考郭炜老师课件上的代码。思路是建立一个超级源点和一个超级汇点,先输入的串如果是0000....或02...的形式,则与源点相连,后输入的串如果为1111...则与超级汇点相连。

    然后拆点,把从入机器前的状态到如机器后的状态看成一个流,流的最大量就是该机器每小时可以加工的元件数。然后用EK的优化——Dinic。思路就是在先用bfs把图中所有的结点标上按遍历的顺序标上层次,这样找到一条增广路径后就不需要退到0号结点,而是推倒所找的增广路径上跟下一个结点的容量是最小容量的那个结点。、

    Code:

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <queue>

    using namespace std;

    const int M = 110;
    const int inf = 0x6fffffff;

    struct machine {
    int l;
    int in[11];
    int out[11];
    }mach[M];

    int g[M][M];
    int fg[M][M];
    int layer[M];
    bool vis[M];
    int P, N, T;

    bool Equal(int *a, int *b, int P) {
    for(int i = 0; i < P; i++) {
    if(a[i] + b[i] == 1) return false;
    }
    return true;
    }

    bool Layer() {
    deque<int> q;
    int i, v;
    memset(layer, -1, sizeof(layer));
    q.push_back(0);
    layer[0] = 1;
    while( !q.empty()) {
    v = q.front();
    q.pop_front();
    for(i = 0; i <= T; i++) {
    if(g[v][i] > 0 && layer[i] == -1) {
    layer[i] = layer[v] + 1;
    if(i == T) {q.clear(); return true;}
    else q.push_back(i);
    }
    }
    }
    return false;
    }

    int Dinic() {
    int i, v, sum = 0, Min, Min_s, s, e;

    deque<int> q;
    while(Layer()) {
    memset(vis, 0, sizeof(vis));
    vis[0] = true;
    q.push_back(0);
    while(!q.empty()) {
    v = q.back();
    if(v == T) {
    Min = inf;
    for(i = 1; i < q.size(); i++) {
    s = q[i-1];
    e = q[i];
    if(g[s][e] > 0 && Min > g[s][e]) {
    Min = g[s][e];
    Min_s = s;
    }
    }
    sum += Min;
    for(i = 1; i < q.size(); i++) {
    s = q[i-1];
    e = q[i];
    if(g[s][e] > 0) {
    g[s][e] -= Min;
    g[e][s] += Min;
    }
    }
    while(!q.empty() && q.back() != Min_s) {
    vis[q.back()] = false;
    q.pop_back();
    }
    } else {
    for(i = 0; i <= T; i++) {
    if(g[v][i] > 0 && layer[i] == layer[v] + 1 && !vis[i]) {
    vis[i] = true;
    q.push_back(i);
    break;
    }
    }
    if(i > T) q.pop_back();
    }
    }
    }
    return sum;
    }

    int main() {
    //freopen("data.in", "r", stdin);

    int i, j, k, sum, edg;
    while(~scanf("%d%d", &P, &N)) {
    memset(g, 0, sizeof(g));
    memset(mach, 0, sizeof(mach));
    for(i = 1; i <= N; i++) {
    scanf("%d", &mach[i].l);
    for(j = 0; j < P; j++)
    scanf("%d", &mach[i].in[j]);
    for(j = 0; j < P; j++)
    scanf("%d", &mach[i].out[j]);
    g[i][i+N] = mach[i].l;
    }
    T = 2 * N + 1;
    for(i = 1; i <= N; i++) {
    for(j = i+1; j <= N; j++) {
    if(Equal(mach[i].out, mach[j].in, P))
    g[i+N][j] = inf;
    if(Equal(mach[j].out, mach[i].in, P))
    g[j+N][i] = inf;
    }
    g[0][i] = inf;
    for(k = 0; k < P; k++) {
    if(mach[i].in[k] == 1) {
    g[0][i] = 0; break;
    }
    }
    g[i+N][T] = inf;
    for(k = 0; k < P; k++) {
    if(mach[i].out[k] != 1) {
    g[i+N][T] = 0; break;
    }
    }
    }
    memcpy(fg, g, sizeof(g));
    sum = Dinic();
    edg = 0;
    for(i = N+1; i < T; i++) {
    for(j = 1; j <= N; j++) {
    if(g[i][j] < fg[i][j])
    edg++;
    }
    }
    printf("%d %d\n", sum, edg);
    for(i = N + 1; i < T; i++) {
    for(j = 1; j <= N; j++) {
    if(g[i][j] < fg[i][j])
    printf("%d %d %d\n", i-N, j, fg[i][j] - g[i][j]);
    }
    }
    }
    return 0;
    }



  • 相关阅读:
    华为交换机配置命令总结
    Linux 系统启动项修复
    Linux菜鸟成长日记 ( Linux 下的 ftp 文件传输协议 )
    Linux 查看用户命令
    linux 查看过滤命令命令
    Linux篇---ftp服务器的搭建
    linux挂载详解
    园区IP地址规划(非常详细)
    Linux创建、删除文件和文件夹命令
    CentOs 7 安装 Xampp
  • 原文地址:https://www.cnblogs.com/vongang/p/2247583.html
Copyright © 2011-2022 走看看