您的位置:首页 > 理论基础 > 计算机网络

LibreOJ #6000. 「网络流 24 题」搭配飞行员

2017-06-25 15:19 405 查看
二次联通门 : LibreOJ #6000. 「网络流 24 题」搭配飞行员

/*
LibreOJ #6000. 「网络流 24 题」搭配飞行员

二分图最大匹配
Dinic最大流 + 当前弧优化

*/
#include <cstring>
#include <cstdio>
#include <queue>

#define Max 10000
#define INF 1e5

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

inline int min (int a, int b)
{
return a < b ? a : b;
}

class Net_Flow_Type
{

private :

int __to[Max << 2], __next[Max << 2];

int __flow[Max << 2];

int edge_list[Max];
int Edge_Count;

int deep[Max], __tech_[Max];
int T;

int Answer;

public :

Net_Flow_Type ()
{
Edge_Count = 1;
}

inline void Insert_edge (int from, int to)
{
Edge_Count ++;

__to[Edge_Count] = to;
__next[Edge_Count] = edge_list[from];
edge_list[from] = Edge_Count;

Edge_Count ++;

__to[Edge_Count] = from;
__next[Edge_Count] = edge_list[to];
edge_list[to] = Edge_Count;

__flow[Edge_Count - 1] = 1;
__flow[Edge_Count] = 0;
}

bool Bfs (int Start, int End)
{
std :: queue <int> Queue;

Queue.push (Start);
memset (deep, -1, sizeof deep);

int now;
for (deep[Start] = 0; !Queue.empty (); Queue.pop ())
{
now = Queue.front ();

for (int i = edge_list[now]; i; i = __next[i])
if (__flow[i] && deep[__to[i]] == -1)
{
deep[__to[i]] = deep[now] + 1;
if (__to[i] == End)
return true;
Queue.push (__to[i]);
}
}

return deep[End] != -1;
}

int Flowing (int now, int flow)
{
if (now == T || flow <= 0)
return flow;

int res = 0, pos = 0;
for (int i = __tech_[now]; i; i = __next[i])
{
if (deep[__to[i]] != deep[now] + 1 || __flow[i] <= 0)
continue;
res = Flowing (__to[i], min (flow, __flow[i]));

if (res > 0)
{
flow -= res;
pos += res;

__flow[i] -= res;
__flow[i ^ 1] += res;
if (__flow[i])
__tech_[now] = i;

if (flow == 0)
return pos;
}
}
return pos;
}

int Dinic (int Start, int End)
{
for (T = End; Bfs (Start, End); )
{
memcpy (__tech_, edge_list, sizeof edge_list);

Answer += Flowing (Start, INF);
}

return Answer;
}

};

int N, M;
Net_Flow_Type Make;

int main (int argc, char *argv[])
{
read (N);
read (M);

int S = N + 1, T = N + 2;

for (int i = 1; i <= M; i ++)
Make.Insert_edge (S, i);

for (int i = M + 1; i <= N; i ++)
Make.Insert_edge (i, T);

for (int x, y; scanf ("%d %d", &x, &y) == 2; Make.Insert_edge (x, y));

printf ("%d", Make.Dinic (S, T));

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: