luogu P1231 教辅的组成

二次联通门 : luogu P1231 教辅的组成

 

 

 

 

/*
    luogu P1231 教辅的组成
    
    拆点 + 最大流
    
    把书拆点后与答案与资料连边
    跑最大流 
*/
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>

#define Max 50005
#define INF 1e7

using namespace std;

void read (int &now)
{
    now = 0;
    char word = getchar ();
    while (word > '9' || word < '0')
        word = getchar ();
    while (word >= '0' && word <= '9')
    {
        now = now * 10 + word - '0';
        word = getchar ();
    }
}

struct Edge
{
    int to;
    int next;
    int flow;
}edge[Max << 3];

int Edge_Count = 1;
int edge_list[Max];

inline void AddEdge (int from, int to)
{
    Edge_Count++;
    edge[Edge_Count].flow = 1;
    edge[Edge_Count].to = to;
    edge[Edge_Count].next = edge_list[from];
    edge_list[from] = Edge_Count;
    Edge_Count++;
    edge[Edge_Count].to = from;
    edge[Edge_Count].flow = 0;
    edge[Edge_Count].next = edge_list[to];
    edge_list[to] = Edge_Count;
}

int N, M, Q;
int E;
int S, T;
int deep[Max];
int Answer;

int Flowing (int now, int flow)
{
    if (flow <= 0 || now == T)
        return flow;
    int pos = 0, res = 0;
    for (int i = edge_list[now]; i; i = edge[i].next)
    {
        if (deep[edge[i].to] != deep[now] + 1 || edge[i].flow <= 0)
            continue;
        pos = Flowing (edge[i].to, min (edge[i].flow, flow));
        flow -= pos;
        res += pos;
        edge[i].flow -= pos;
        edge[i ^ 1].flow += pos;
        if (flow <= 0)
            return res;
    }
    return res;
}

int main (int argc, char *argv[])
{
    read (N);
    read (M);
    read (Q);
    read (E);
    M += N;
    Q += M;
    S = Max - 2;
    T = Max - 3;
    int x, y;
    for (int i = 1; i <= N; i++)
        AddEdge (i, i + Q);
    for (int i = N + 1; i <= M; i++)
        AddEdge (S, i);
    for (int i = M + 1; i <= Q; i++)
        AddEdge (i, T);
    for (int i = 1; i <= E; i++)
    {
        read (x);
        read (y);
        AddEdge (y + N, x);
    }
    read (E);
    for (int i = 1; i <= E; i++)
    {
        read (x);
        read (y);
        AddEdge (x + Q, y + M);
    }
    while (true)
    {
        bool flag = false;
        memset (deep, -1, sizeof deep);
        queue <int> Queue;
        Queue.push (S);
        deep[S] = 0;
        int now;
        while (!Queue.empty ())
        {
            now = Queue.front ();
            Queue.pop ();
            for (int i = edge_list[now]; i; i = edge[i].next)
                if (deep[edge[i].to] < 0 && edge[i].flow)
                {
                    deep[edge[i].to] = deep[now] + 1;
                    if (edge[i].to == T)
                    {
                        flag = true;
                        break;
                    }
                    Queue.push (edge[i].to); 
                }
            if (flag)
                break;
        }
        if (deep[T] < 0)
            break;
        Answer += Flowing (S, INF);
    }
    printf ("%d", Answer);
    return 0;
}

 

posted @ 2017-05-20 17:41  ZlycerQan  阅读(165)  评论(0编辑  收藏  举报