「 Luogu P1231 」 教辅的组成

题目大意

有 $\text{N1}$ 本书 $\text{N2}$本练习册 $\text{N3}$本答案,一本书只能和一本练习册和一本答案配对。给你一些书和练习册,书和答案的可能的配对关系。问你最多可以配成多少套完整的书册。

 

解题思路

我已开始直接建立超级源点汇点,然后源点$\rightarrow $练习册连边,练习册$\rightarrow $书连边,书$\rightarrow $答案连边,答案$\rightarrow $汇点连边。然后直接跑 $\text{Dinic}$。$\text{RE}$ 了之后 $\text{TLE}$ 了。后来发现如果「 书 」这个环节不进行拆点的话,会有部分练习册和答案共用一本书。这样就错了。又加了拆点的过程。还是 $\text{TLE}$。又发现是我的$\text{Dinic}$ 写的太丑,每次增广只能增广 $1$ 。简直了,又去题解,里找了个写的好看的 $\text{Dinic}$ 重新搞了一线板子,这才过了这道题。

 

附上代码

#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
using namespace std;
const int maxn = 8e6+3, INF = 2147483647;
int n1, n2, n3, s, t, m, head[maxn], cnt = 1, Depth[maxn], Ans;
struct edge {
    int v, w, nxt;
}ed[maxn];
inline int read() {
    int x = 0, f = 1; char c = getchar();
    while (c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
    while (c <= '9' && c >= '0') {x = x*10 + c-'0'; c = getchar();}
    return x * f;
}
inline void addedge (int x, int y, int z) {
    ed[++cnt].nxt = head[x];
    ed[cnt].v = y, ed[cnt].w = z;
    head[x] = cnt;
}
inline bool bfs() {
    queue<int> Q;
    memset(Depth, 0, sizeof(Depth));
    Q.push(s), Depth[s] = 1;
    int u;
    while (!Q.empty()) {
        u = Q.front();
        Q.pop();
        for(int i=head[u]; i; i=ed[i].nxt) {
            if(ed[i].w > 0 && !Depth[ed[i].v]) {
                Depth[ed[i].v] = Depth[u] + 1;
                Q.push(ed[i].v);
                if(ed[i].v == t) return true;
            }
        }
    }
    return false;
}
inline int Dinic(int u, int cap) {
    if(u == t || !cap) return cap;
    int delta, ret = 0;
    for(int i=head[u]; i; i=ed[i].nxt) {
        if(ed[i].w > 0 && Depth[ed[i].v] == Depth[u] + 1) {
            delta = Dinic(ed[i].v, min(ed[i].w, cap-ret));
            if(delta > 0) {
                ed[i].w -= delta;
                ed[i^1].w += delta;
                ret += delta;
            }
        }
    }
    return ret;
}
int main() {
    n1 = read(), n2 = read(), n3 = read();
    s = 0, t = n1*2+n2+n3+1;
    for(int i=n1*2+1; i<=n1*2+n2; i++)
        addedge(s, i, 1), addedge(i, s, 0);
    for(int i=n1*2+n2+1; i<=n1*2+n2+n3; i++)
        addedge(i, t, 1), addedge(t, i, 0);
    scanf("%d", &m);
    int x, y;
    for(int i=1; i<=m; i++) {
        scanf("%d%d", &x, &y);
        addedge(y+n1*2, x, 1), addedge(x, y+n1*2, 0);
    }
    scanf("%d", &m);
    for(int i=1; i<=m; i++) {
        scanf("%d%d", &x, &y);
        addedge(x+n1, y+n1*2+n2, 1), addedge(y+n1*2+n2, x+n1, 0);
    }
    for(int i=1; i<=n1; i++) {
        addedge(i, i+n1, 1), addedge(i+n1, i, 0);
    }
    while (bfs()) Ans += Dinic(s, INF);
    printf("%d", Ans);
}

 

posted @ 2018-09-03 16:07  Mystical-W  阅读(235)  评论(0编辑  收藏  举报