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

全部评论

相关推荐

点赞 评论 收藏
分享
能干的三文鱼刷了10...:公司可能有弄嵌入式需要会画pcb的需求,而且pcb能快速直观看出一个人某方面的实力。看看是否有面试资格。问你问题也能ai出来,pcb这东西能作假概率不高
点赞 评论 收藏
分享
07-25 11:26
清华大学 Java
打开电脑,思绪又回到了7月份刚开始的时候,感觉这个月过的如梦如幻,发生了太多事,也算是丰富了我本就是平淡的人生吧太早独立的我习惯了一切都是自己做决定,拥有绝对的决定权,而且永远不会听取别人的建议。我就是那个恋爱四年出轨的男主啦,感觉既然在牛客开了这个头,那我就要做个有始有终的人。从我出轨到结束再到和女朋友和好如初真的太像一场梦了,短短的一个月我经历了太多,也成长了很多,放下了那些本就不属于我的,找回了那些我不该放弃的。我的人生丰富且多彩,但人不能一直顺,上天总会让你的生活中出点乱子,有好有坏,让你学会一些东西,让你有成长。我和女朋友的恋爱四年太过于平淡,日常除了会制造一些小浪漫之外,我们的生活...
段哥亡命职场:不得不说,我是理解你的,你能发出来足见你是个坦诚的人,至少敢于直面自己的内心和过往的过错。 这个世界没有想象中那样非黑即白,无论是农村还是城市,在看不见的阴影里,多的是这样的事。 更多的人选择站在制高点去谩骂,一方面是社会的道德是需要制高点的,另一方面,很多人不经他人苦,却劝他人善。 大部分的我们,连自己生命的意义尚且不能明晰,道德、法律、困境,众多因果交织,人会迷失在其中,只有真的走出来之后才能看明白,可是没走出来的时候呢?谁又能保证自己能走的好,走的对呢? 可是这种问题有些人是遇不到的,不去追寻,不去探寻,也就没了这些烦恼,我总说人生的意义在过程里,没了目标也就没了过程。 限于篇幅,没法完全言明,总之,这世界是个巨大的草台班子,没什么过不去了,勇敢面对,革故鼎新才是正确,祝你早日走出来。查看图片
点赞 评论 收藏
分享
评论
1
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务