P1231 教辅的组成

时隔多日再次打网络流就错了。。。


跟那道“酒店之王”几乎一模一样,只不过数据大些,加当前弧照样过。

从luogu题解偷来一张图,有这张图就不用说话了。。。

代码:

#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>

const int maxn = 10005, maxm = 20005, INF = 19260817;
struct Edges
{
    int next, to, weight;
} e[maxm << 4];
int head[maxn], tot = 1;
int n1, n2, n3, m1, m2, s, t;
int dep[maxn], cur[maxn];
void link(int u, int v, int w)
{
    e[++tot] = (Edges){head[u], v, w};
    head[u] = tot;
}
void addEdges(int u, int v, int w)
{
    link(u, v, w), link(v, u, 0);
}
int read()
{
    int ans = 0; char ch = getchar();
    while(ch > '9' || ch < '0') ch = getchar();
    while(ch >= '0' && ch <= '9')
    {
        ans = ans * 10 + ch - '0';
        ch = getchar();
    }
    return ans;
}
bool bfs()
{
    memset(dep, 0, sizeof(dep));
    std::queue<int> q;
    q.push(s); dep[s] = 1;
    while(!q.empty())
    {
        int u = q.front(); q.pop();
        for(int i = head[u]; i; i = e[i].next)
        {
            int v = e[i].to;
            if(!dep[v] && e[i].weight > 0)
            {
                q.push(v);
                dep[v] = dep[u] + 1;
            }
        }
    }
    return dep[t];
}
int dfs(int u, int flow)
{
    if(u == t) return flow;
    for(int &i = cur[u]; i; i = e[i].next)
    {
        int v = e[i].to;
        if(dep[v] == dep[u] + 1 && e[i].weight > 0)
        {
            int di = dfs(v, std::min(flow, e[i].weight));
            if(di)
            {
                e[i].weight -= di;
                e[i ^ 1].weight += di;
                return di;
            }
        }
    }
    return 0;
}
int dinic()
{
    int ans = 0;
    while(bfs())
    {
        for(int i = 1; i <= t; i++) cur[i] = head[i];
        while(int temp = dfs(s, INF)) ans += temp;
    }
    return ans;
}
// this is the intro of index
// [1, n2] exercises
// [n2 + 1, n2 + n1] books_1 [n2 + n1 + 1, n2 + n1 + n1] books_2
// [n2 + n1 + n1 + 1, n2 + n1 + n1 + n3] answers
// s = n2 + n1 + n1 + n3 + 1; t = s + 1;
int main()
{
    n1 = read(), n2 = read(), n3 = read();
    m1 = read();
    while(m1--)
    {
        int x = read(), y = read();
        addEdges(y, n2 + x, 1);
    }
    m2 = read();
    while(m2--)
    {
        int x = read(), y = read();
        addEdges(n2 + n1 + x, n2 + n1 + n1 + y, 1);
    }
    s = n2 + n1 + n1 + n3 + 1; t = s + 1;
    for(int i = 1; i <= n2; i++) addEdges(s, i, 1);
    for(int i = 1; i <= n1; i++) addEdges(n2 + i, n2 + n1 + i, 1);
    for(int i = 1; i <= n3; i++) addEdges(n2 + n1 + n1 + i, t, 1);

    printf("%d\n", dinic());
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/Garen-Wang/p/9338908.html
今日推荐