luogu P2756 飞行员配对方案问题

二次联通门 : luogu P2756 飞行员配对方案问题

 

 

 

 

/*
    luogu P2756 飞行员配对方案问题
    
    二分图匹配 
    
    输出时略麻烦 
    从源点开始
        若扫到的下一条边的流量为0
        则证明该条边可以
            再枚举当前点的边,记录答案
            最后输出即可 
*/
#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>

#define Max 202
#define INF 1e7

using namespace std;


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

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

int Edge_Count = 1;
int edge_list[Max];
int N, M;
int S = 0, T;

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].flow = 0;
    edge[Edge_Count].to = from;
    edge[Edge_Count].next = edge_list[to];
    edge_list[to] = Edge_Count;
}

int deep[Max];

int Flowing (int now, int flow)
{
    if (flow <= 0 || now == T)
        return flow;
    int pos, 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));
        res += pos;
        flow -= pos;
        edge[i].flow -= pos;
        edge[i ^ 1].flow += pos;
        if (flow == 0)
            return res;
    }
    return res;
}

struct Link
{
    int first;
    int second;
}link[Max];

int main (int argc, char *argv[])
{
    read (M);
    read (N);
    T = N + 2;
    int x, y;
    while (scanf ("%d%d", &x, &y) && x != -1 && y != -1)
        AddEdge (x, y);
    for (int i = 1; i <= M; i++)
        AddEdge (S, i);
    for (int i = M + 1; i <= N; i++)
        AddEdge (i, T);
    int Answer = 0;
    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);
    }
    if (!Answer)
    {
        printf ("No Solution!");
        return 0;
    }
    printf ("%d\n", Answer);
    int Count = 0;
    for (int i = edge_list[S]; i; i = edge[i].next)
        if (!edge[i].flow)
            for (int j = edge_list[edge[i].to]; j; j = edge[j].next)
                if (!edge[j].flow)
                {
                    if (edge[i].to == T || edge[j].to == S || edge[i].to == S || edge[j].to == T)
                        continue;
                    Count++;
                    link[Count].first = edge[i].to;
                    link[Count].second = edge[j].to;
                }
    for (int i = 1; i <= Count; i++)
        printf ("%d %d\n", link[i].first, link[i].second);
    return 0;
}

 

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