ACM Computer Factory

水题

看到oj下面好多人说拆点。但是,我没有拆点却也做出来了。
从网络流的角度都去想没有什么障碍。我们构造出源点s和汇点t
然后看有哪些机器可以和源点连,即input清一色为0或2 连(s,i)cap=Q[i]
看有哪些可以可以与汇点连,即output都为1 连(i,t) cap = Q[i]

然后再看那些机器可以对接,i,j可以对接,即对于j的input,i的output可以满足
注意的是,这里连的边cap=Q[i]

再跑一便最大流就可以了!!!!

代码如下:

#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
typedef pair<int, int> pii;
typedef pair<int, pii> pip;
const int inf = 2e9;
struct edge{
    int to, cap, rev, next;
}E[10000];
int head[55];
int cnt = 1;
void add(int from, int to, int cap,int rev) {
    E[cnt].to = to;E[cnt].next = head[from];
    E[cnt].cap = cap;
    E[cnt].rev = rev;head[from] = cnt++;
}
int P, N;
int Q[60];
int in[60][15];
int out[60][15];

bool check_ed(int id) {
    for (int i = 1;i <= P;++i)
        if (out[id][i] != 1)return false;
    return true;
}
bool check_st(int id) {
    for (int i = 1;i <= P;++i)
        if (in[id][i] == 1)return false;
    return true;
}
bool check_ij(int ma, int mb) {
    for (int i = 1;i <= P;++i) {
        if (in[mb][i] == 1 && out[ma][i] == 0)return false;
        if (in[mb][i] == 0 && out[ma][i] == 1)return false;
    }return true;
}

int d[55];
bool searchpath(int s,int t) {
    fill(d, d + 55, -1);
    queue<int> que;d[s] = 0;
    que.push(s);
    while (!que.empty()) {
        int u = que.front();
        que.pop();
        for (int i = head[u];i;i = E[i].next) {
            edge& e = E[i];
            if (d[e.to] != -1 || e.cap <= 0)continue;
            d[e.to] = d[u] + 1;
            que.push(e.to);
        }
    }return d[t] != -1;
}
int matchpath(int u,int t,int f) {
    if(u == t)return f;
    for (int i = head[u];i;i = E[i].next) {
        edge& e = E[i];
        if (d[e.to] <= d[u] || e.cap <= 0)continue;
        int flow = matchpath(e.to, t, min(f, e.cap));
        if (flow > 0) {
            e.cap -= flow;
            E[e.rev].cap += flow;
            return flow;
        }
    }return false;
}
int dinic(int st,int ed) {
    int flow = 0;int f;
    while (searchpath(st, ed))
        while (f = matchpath(st, ed, inf))
            flow += f;
    return flow;
}


vector<pip> res;
bool vis[55];
void bfs(int s,int t) {
    res.clear();
    fill(vis, vis + 55, false);
    queue<int> que;
    que.push(s);vis[s] = true;
    while (!que.empty()) {
        int u = que.front();
        que.pop();vis[u] = false;
        for (int i = head[u];i;i = E[i].next) {
            edge& e = E[i];
            if (e.rev & 1)continue;
            if (E[e.rev].cap == 0)continue;
            if (!vis[e.to]) {
                que.push(e.to);
                vis[e.to] = true;
            }
            if (u != s && e.to != t)
                res.push_back(make_pair(E[e.rev].cap, make_pair(u, e.to)));
        }
    }
}

int main() {
    while (scanf("%d %d", &P, &N)!=EOF) {
        if (P == 0 && N == 0)break;
        fill(head, head + 55, 0);cnt = 1;
        for (int i = 1;i <= N;++i) {
            scanf("%d", &Q[i]);
            for (int j = 1;j <= P;++j)scanf("%d", &in[i][j]);
            for (int j = 1;j <= P;++j)scanf("%d", &out[i][j]);
        }int start = N + 1;int ed = start + 1;
        for (int i = 1;i <= N;++i) {
            if (check_st(i)) {
                add(start, i, Q[i], cnt + 1);
                add(i, start, 0, cnt - 1);
            }
            if (check_ed(i)) {
                add(i, ed, Q[i], cnt + 1);
                add(ed, i, 0, cnt - 1);
            }
            for (int j = 1;j <= N;++j) {
                if (j != i && check_ij(i, j)) {
                    add(i, j, Q[i], cnt + 1);
                    add(j, i, 0, cnt - 1);
                }
            }
        }printf("%d ", dinic(start, ed));
        bfs(start, ed);printf("%d", res.size());
        for (int i = 0;i < res.size();++i)
            printf("\n%d %d %d", res[i].second.first, res[i].second.second, res[i].first);
    }
}
kuangbin题单刷题详解(网络流) 文章被收录于专栏

题单:https://vjudge.net/article/371

全部评论

相关推荐

AaronRuan:看到了好多开奖了,不知道为啥自己也有点激动,真的替你们感到高兴啊
投递华为等公司10个岗位
点赞 评论 收藏
分享
斑驳不同:还为啥暴躁 假的不骂你骂谁啊
点赞 评论 收藏
分享
评论
1
收藏
分享
牛客网
牛客企业服务