POJ - 3281 Dining (ISAP EK Dinic)

题目大意:有N头牛,F种食物,D种饮料,每种食物和饮料都只有一

现在给出每头牛所喜爱的食物和饮料,问最多有多少头牛能同时得到自己喜欢的食物和饮料

解题思路:将牛拆成两点,权值为1,一条和喜欢的食物相连,权值为1,另一条和喜欢的饮料相连,权值为1

然后将所有食物和超级源点相连,权值为1

将所有的饮料喝超级汇点相连,权值为1

ISAP

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
using namespace std;
#define N 1010
#define INF 0x3f3f3f3f

struct Edge {
    int from, to, cap, flow;
    Edge() {}
    Edge(int from, int to, int cap, int flow): from(from), to(to), cap(cap), flow(flow) {}
};

struct ISAP {
    int p[N], num[N], cur[N], d[N];
    int t, s, n, m;
    bool vis[N];

    vector<int> G[N];
    vector<Edge> edges;

    void init(int n) {
        this->n = n;
        for (int i = 0; i <= n; i++) {
            G[i].clear();
            d[i] = INF;
        }
        edges.clear();
    }

    void AddEdge(int from, int to, int cap) {
        edges.push_back(Edge(from, to, cap, 0));
        edges.push_back(Edge(to, from, 0, 0));
        int m = edges.size();
        G[from].push_back(m - 2);
        G[to].push_back(m - 1);
    }

    bool BFS() {
        memset(vis, 0, sizeof(vis));

        queue<int> Q;
        d[t] = 0;
        vis[t] = 1;
        Q.push(t);

        while (!Q.empty()) {
            int u = Q.front();
            Q.pop();

            for (int i = 0; i < G[u].size(); i++) {
                Edge &e = edges[G[u][i] ^ 1];
                if (!vis[e.from] && e.cap > e.flow) {
                    vis[e.from] = true;
                    d[e.from] = d[u] + 1;
                    Q.push(e.from);
                }
            }
        }
        return vis[s];
    }

    int Augment() {
        int u = t, flow = INF;
        while (u != s) {
            Edge &e = edges[p[u]];
            flow = min(flow, e.cap - e.flow);
            u = edges[p[u]].from;
        }

        u = t;
        while (u != s) {
            edges[p[u]].flow += flow;
            edges[p[u] ^ 1].flow -= flow;
            u = edges[p[u]].from;
        }
        return flow;
    }

    int Maxflow(int s, int t) {
        this->s = s; this->t = t;
        int flow = 0;
        BFS();
        if (d[s] > n)
            return 0;

        memset(num, 0, sizeof(num));
        memset(cur, 0, sizeof(cur));
        for (int i = 0; i < n; i++)
            if (d[i] < INF)
                num[d[i]]++;
        int u = s;

        while (d[s] <= n) {
            if (u == t) {
                flow += Augment();
                u = s;
            }
            bool ok = false;
            for (int i = cur[u]; i < G[u].size(); i++) {
                Edge &e = edges[G[u][i]];
                if (e.cap > e.flow && d[u] == d[e.to] + 1) {
                    ok = true;
                    p[e.to] = G[u][i];
                    cur[u] = i;
                    u = e.to;
                    break;
                }
            }

            if (!ok) {
                int Min = n;
                for (int i = 0; i < G[u].size(); i++) {
                    Edge &e = edges[G[u][i]];
                    if (e.cap > e.flow)
                        Min = min(Min, d[e.to]);
                }
                if (--num[d[u]] == 0)
                    break;
                num[d[u] = Min + 1]++;
                cur[u] = 0;
                if (u != s)
                    u = edges[p[u]].from;
            }
        }
        return flow;
    }
};

//cow 1 -- 2 * n
//food 2 * n + 1 --- 2 * n + f
//drink 2 * n + f + 1 --- 2 * n + f + d
//start 0
//sink 2 * n + f + d + 1

ISAP isap;
int n, f, d;

void init() {
    int s = 0, t = 2 * n + d + f + 1;
    isap.init(t);

    for (int i = 1; i <= f; i++) {
        isap.AddEdge(0, 2 * n + i, 1);
    }

    for (int i = 1; i <= d; i++) {
        isap.AddEdge(2 * n + f + i, t, 1);
    }

    int fi, di, x;
    for (int i = 1; i <= n; i++)  {
        scanf("%d%d", &fi, &di);
        isap.AddEdge(i, n + i, 1);

        for (int j = 0; j < fi; j++) {
            scanf("%d", &x);
            isap.AddEdge(2 * n + x, i, 1);
        }

        for (int j = 0; j < di; j++) {
            scanf("%d", &x);
            isap.AddEdge(n + i, 2 * n + f + x, 1);
        }
    }
    int flow = isap.Maxflow(s, t);

    printf("%d\n", flow);
}

int main() {
    while (scanf("%d%d%d", &n, &f, &d) != EOF) {
        init();
    }
    return 0;
}

Dinic

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
using namespace std;
#define N 1010
#define INF 0x3f3f3f3f

struct Edge{
    int from, to, cap, flow;
    Edge() {}
    Edge(int from, int to, int cap, int flow) : from(from), to(to), cap(cap), flow(flow) {}
};

struct Dinic{
    int n, m, s, t;
    vector<Edge> edges;
    vector<int> G[N];
    bool vis[N];
    int d[N], cur[N];

    void init(int n) {
        this->n = n;
        for (int i = 0; i <= n; i++) {
            G[i].clear();
        }
        edges.clear();
    }

    void AddEdge(int from, int to, int cap) {
        edges.push_back(Edge(from, to, cap, 0));
        edges.push_back(Edge(to, from, 0, 0));
        int m = edges.size();
        G[from].push_back(m - 2);
        G[to].push_back(m - 1);
    } 

    bool BFS() {
        memset(vis, 0, sizeof(vis));
        queue<int> Q;
        Q.push(s);
        vis[s] = 1;
        d[s] = 0;

        while (!Q.empty()) {
            int u = Q.front();
            Q.pop();
            for (int i = 0; i < G[u].size(); i++) {
                Edge &e = edges[G[u][i]];
                if (!vis[e.to] && e.cap > e.flow) {
                    vis[e.to] = true;
                    d[e.to] = d[u] + 1;
                    Q.push(e.to);
                }
            }
        }
        return vis[t];
    }

    int DFS(int x, int a) {
        if (x == t || a == 0)
            return a;

        int flow = 0, f;
        for (int i = cur[x]; i < G[x].size(); i++) {
            Edge &e = edges[G[x][i]];
            if (d[x] + 1 == d[e.to] && (f = DFS(e.to, min(a, e.cap - e.flow))) > 0) {
                e.flow += f;
                edges[G[x][i] ^ 1].flow -= f;
                flow += f;
                a -= f;
                if (a == 0)
                    break;
            }
        }
        return flow;
    }

    int Maxflow(int s, int t) {
        this->s = s; this->t = t;
        int flow = 0;
        while (BFS()) {
            memset(cur, 0, sizeof(cur));
            flow += DFS(s, INF);
        }
        return flow;
    }
};

Dinic dinic;

//cow 1 -- 2 * n
//food 2 * n + 1 --- 2 * n + f
//drink 2 * n + f + 1 --- 2 * n + f + d
//start 0
//sink 2 * n + f + d + 1

int n, f, d;

void init() {
    int s = 0, t = 2 * n + d + f + 1;
    dinic.init(t);

    for (int i = 1; i <= f; i++) {
        dinic.AddEdge(0, 2 * n + i, 1);
    }

    for (int i = 1; i <= d; i++) {
        dinic.AddEdge(2 * n + f + i, t, 1);
    }

    int fi, di, x;
    for (int i = 1; i <= n; i++)  {
        scanf("%d%d", &fi, &di);
        dinic.AddEdge(i, n + i, 1);

        for (int j = 0; j < fi; j++) {
            scanf("%d", &x);
            dinic.AddEdge(2 * n + x, i, 1);
        }

        for (int j = 0; j < di; j++) {
            scanf("%d", &x);
            dinic.AddEdge(n + i, 2 * n + f + x, 1);
        }
    }
    int flow = dinic.Maxflow(s, t);

    printf("%d\n", flow);
}

int main() {
    while (scanf("%d%d%d", &n, &f, &d) != EOF) {
        init();
    }
    return 0;
}

EK

#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
#include <vector>
using namespace std;
#define N 1010
#define INF 0x3f3f3f3f

struct Edge{
    int from, to, cap, flow;
    Edge() {}
    Edge(int from, int to, int cap, int flow): from(from), to(to), cap(cap), flow(flow){}
};

struct EK{
    vector<int> G[N];
    vector<Edge> edges;
    int s, t, n, m, p[N];
    bool vis[N];

    void init(int n) {
        this->n = n;
        for (int i = 0; i <= n; i++)
            G[i].clear();
        edges.clear();
    }

    void AddEdge(int from, int to, int cap) {
        edges.push_back(Edge(from, to, cap, 0));
        edges.push_back(Edge(to, from, 0, 0));
        m = edges.size();
        G[from].push_back(m - 2);
        G[to].push_back(m - 1);
    }

    bool BFS() {
        queue<int> q;
        memset(vis, 0, sizeof(vis));
        vis[s] = 1;
        q.push(s);

        while (!q.empty()) {
            int u = q.front();
            q.pop();

            for (int i = 0; i < G[u].size(); i++) {
                Edge &e = edges[G[u][i]];
                if (!vis[e.to] && e.cap > e.flow) {
                    vis[e.to] = true;
                    p[e.to] = G[u][i];
                    if (e.to == t)
                        return true;
                    q.push(e.to);
                }
            }
        }
        return false;
    }

    int Augment() {
        int flow = INF, u = t;
        while (u != s) {
            Edge &e = edges[p[u]];
            flow = min(flow, e.cap - e.flow);
            u = e.from;
        }

        u = t;
        while (u != s) {
            edges[p[u]].flow += flow;
            edges[p[u] ^ 1].flow -= flow;
            u = edges[p[u]].from;
        }
        return flow;
    }

    int Maxflow(int s, int t) {
        this->s = s; this->t = t;
        int flow = 0;

        while (BFS()) {
            flow += Augment();
        }
        return flow;
    }
};

EK ek;

//cow 1 -- 2 * n
//food 2 * n + 1 --- 2 * n + f
//drink 2 * n + f + 1 --- 2 * n + f + d
//start 0
//sink 2 * n + f + d + 1

int n, f, d;

void init() {
    int s = 0, t = 2 * n + d + f + 1;
    ek.init(t);

    for (int i = 1; i <= f; i++) {
        ek.AddEdge(0, 2 * n + i, 1);
    }

    for (int i = 1; i <= d; i++) {
        ek.AddEdge(2 * n + f + i, t, 1);
    }

    int fi, di, x;
    for (int i = 1; i <= n; i++)  {
        scanf("%d%d", &fi, &di);
        ek.AddEdge(i, n + i, 1);

        for (int j = 0; j < fi; j++) {
            scanf("%d", &x);
            ek.AddEdge(2 * n + x, i, 1);
        }

        for (int j = 0; j < di; j++) {
            scanf("%d", &x);
            ek.AddEdge(n + i, 2 * n + f + x, 1);
        }
    }
    int flow = ek.Maxflow(s, t);

    printf("%d\n", flow);
}

int main() {
    while (scanf("%d%d%d", &n, &f, &d) != EOF) {
        init();
    }
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-12 15:03:32

POJ - 3281 Dining (ISAP EK Dinic)的相关文章

POJ 3281 Dining(网络流拆点)

[题目链接] http://poj.org/problem?id=3281 [题目大意] 给出一些食物,一些饮料,每头牛只喜欢一些种类的食物和饮料, 但是每头牛最多只能得到一种饮料和食物,问可以最多满足几头牛的要求 即同时得到喜欢的饮料和食物 [题解] 建立一个源点连接食物,汇点连接饮料,中间连接牛, 为了防止同一头牛占用多个资源,所以我们对牛进行拆点,限流为1. [代码(Isap)] #include <cstdio> #include <cstring> using names

POJ - 3436 ACM Computer Factory (ISAP EK Dinic)

题目大意:有N台机器,每台机器能处理相应型态的电脑,处理完后,电脑将变成另一种形态. 每台机器有相应的工作限度,每次至多处理K台 现在问,在一次流水线生产中,最多可以产生多少台完整的电脑(流水线指的是在每一台机器的工作限度下) 解题思路:题目比较难理解,理解题目的话,就比较好做了 首先,将每台机器的点拆成两个点,权值为工作限度 如果机器能处理的电脑的状态全是0的话,就将其和超级源点连接,表示该机器进行第一步加工 如果机器处理完后的形态与另一台机器能处理的最初形态相同,就将其连线,表示下一台机器可

POJ 3281 Dining(最大流dinic&amp;&amp;SAP)

Description Cows are such finicky eaters. Each cow has a preference for certain foods and drinks, and she will consume no others. Farmer John has cooked fabulous meals for his cows, but he forgot to check his menu against their preferences. Although

poj 3281 Dining(网络流+拆点)

Dining Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 20052   Accepted: 8915 Description Cows are such finicky eaters. Each cow has a preference for certain foods and drinks, and she will consume no others. Farmer John has cooked fabulo

POJ 3281 Dining(最大流建图 &amp;&amp; ISAP &amp;&amp; 拆点)

题目链接:http://poj.org/problem?id=3281 努力练建图ing!!! 题意:有 N 头牛,有 F 种食物和 D 种饮料,每种食物或饮料只能供一头牛享用,且每头牛只享用一种食物和一种饮料. 第2行-第N+1行.是牛i 喜欢A种食物,B种饮料,及食物种类列表和饮料种类列表. 问最多能使几头牛同时享用到自己喜欢的食物和饮料.->最大流. 本题难点是建图: 思路:一般都是左边一个集合表示源点与供应相连,右边一个集合表示需求与汇点相连. 但是本题,牛作为需求仍然是一个群体,但是供

poj 3281 Dining(最大流)

poj 3281 Dining Description Cows are such finicky eaters. Each cow has a preference for certain foods and drinks, and she will consume no others. Farmer John has cooked fabulous meals for his cows, but he forgot to check his menu against their prefer

POJ 3281 Dining(最大流)

POJ 3281 Dining 题目链接 题意:n个牛,每个牛有一些喜欢的食物和饮料,每种食物饮料只有一个,问最大能匹配上多少只牛每个牛都能吃上喜欢的食物和喜欢的饮料 思路:最大流,建模源点到每个食物连一条边,容量为1,每个饮料向汇点连一条边容量为1,然后由于每个牛有容量1,所以把牛进行拆点,然后食物连向牛的入点,牛的出点连向食物,跑一下最大流即可 代码: #include <cstdio> #include <cstring> #include <queue> #in

POJ 3228Gold Transportation(二分+最大流)

题目地址:POJ3288 这个题跟之前的一道题混了,感觉是一样的,所以连想都没怎么想就拆点然后求最短路然后二分求最大流了.结果连样例都不过,还一直以为又是哪里手残了..结果看了看样例,手算也确实不对,,.后来就没拆点,直接在原点上建的图,结果样例就过了..然后提交1次AC... 后来仔细的想了想,这题是问每一段路的最短的,而不是整个的最短的.所以说不应该拆点.而我混的那道题(poj2391)是问的走完的总的最小值. 这题的建图就是建一源点与汇点,将每个金矿与源点相连,权值为金矿数,与汇点也相连,

POJ 3071 Football(简单 概率DP)

Football 原文链接:http://blog.csdn.net/xuechelingxiao/article/details/38520105 大意:2^n 个球队进行单场淘汰赛,每两只球队之间比赛会有胜负的概率,问最后谁夺冠的概率最大. 思路:简单的概率DP问题,主要是怎么处理哪两个球队比赛的问题. DP方程为 dp[i][j] = ∑(dp[i-1][j]*dp[i-1][k]*p[j][k]); //dp[i][j]表示第 i 轮的时候,第 j 支队伍赢的概率.. 对于其中位运算,可