hdu 2063 过山车
//最近在看最大流 就那这题练练 开始用EK写的 tle。。。看来EK真的过时了
//dinic 真快
#include <iostream>
using namespace std;
const int MAXN = 510;
const int MAXM = 1010;
int k, n, m;
typedef struct
{
int v, next, cost;
}Edge;
Edge e[MAXM*4];
int p[MAXN*2], q[MAXN*2], level[MAXN*2], que_st[MAXN*2];
int Start, End;
void init()
{//初始化 静态邻接表
scanf("%d %d", &n, &m);
Start = 0, End = n+m+1;
int i, ind = 0;
memset(p, -1, sizeof(p));
for (i = 1; i <= n; ++i)
{
e[ind].v = i;
e[ind].cost = 1;
e[ind].next = p[Start];
p[Start] = ind++;
e[ind].v = Start;
e[ind].cost = 0;
e[ind].next = p[i];
p[i] = ind++;
}
for (i = 1; i <= m; ++i)
{
e[ind].v = End;
e[ind].cost = 1;
e[ind].next = p[i+n];
p[i+n] = ind++;
e[ind].v = i+n;
e[ind].cost = 0;
e[ind].next = p[End];
p[End] = ind++;
}
for (i = 0; i < k; ++i)
{
int from, to;
scanf("%d %d", &from, &to);
e[ind].v = n + to;
e[ind].cost = 1;
e[ind].next = p[from];
p[from] = ind++;
e[ind].v = from;
e[ind].cost = 0;
e[ind].next = p[to+n];
p[to+n] = ind++;
}
}
int Dinic()
{
int Max_Flow = 0;
while (true)
{
int front = 0, last = 0, i;
for (i = 0; i <= n+m+1; ++i)
{
level[i] = 0;
}
level[Start] = 1;
que_st[front] = Start;
while (front <= last)
{//bfs求层次图
int t = que_st[front++];
for (i = p[t]; i != -1; i = e[i].next)
{
if (e[i].cost && !level[e[i].v])
{
level[e[i].v] = level[t] + 1; que_st[++last] = e[i].v;
}
}
}
if (!level[End])
{//汇点不在层次图内 退出
break;
}
for (i = 0; i <= n+m+1; ++i)
{
q[i] = p[i];
}
last = -1;
while (true)
{//栈模拟dfs 用dfs进行增广
if (last < 0)
{//栈空
for (i = q[Start]; i != -1; i = e[i].next)
{//找与源点相邻的边
if (e[i].cost && q[e[i].v] != -1 && level[e[i].v] == 2)
{
break;
}
}
if (i >= 0)
{
que_st[++last] = i;
q[Start] = e[i].next;
}
else
{//与源点相连的边都被删除
break;
}
}
int u = e[que_st[last]].v; //栈中最后的那个顶点
if (u == End)
{//u为汇点 说明找到增广路
int min = 0XFFFFFFF;
int index = -1;
for (i = 0; i <= last; ++i)
{
if (e[que_st[i]].cost < min)
{//可增广的最大值
min = e[que_st[i]].cost;
index = i;
}
}
Max_Flow += min;
for (i = 0; i <= last; ++i)
{//对增广路进行增广
e[que_st[i]].cost -= min;
e[que_st[i]^1].cost += min;
}
//后退至删边后原增广路中可到达的最远点
last = index - 1;
}
else
{//u不是汇点
for (i = q[u]; i != -1; i = e[i].next)
{//找与u相邻的边
if (e[i].cost && q[e[i].v] != -1 && level[e[i].v] == level[u] + 1)
{
break;
}
}
if (i >= 0)
{//找到 则入栈
que_st[++last] = i;
q[u] = e[i].next;
}
else
{//否则 删除点u和与u相邻的所有边
last--;
q[u] = -1;
}
}
}
}
return Max_Flow;
}
int main()
{
while (scanf("%d", &k) != EOF && k)
{
init();
printf("%d\n", Dinic());
}
return 0;
}
//dinic 真快
#include <iostream>
using namespace std;
const int MAXN = 510;
const int MAXM = 1010;
int k, n, m;
typedef struct
{
int v, next, cost;
}Edge;
Edge e[MAXM*4];
int p[MAXN*2], q[MAXN*2], level[MAXN*2], que_st[MAXN*2];
int Start, End;
void init()
{//初始化 静态邻接表
scanf("%d %d", &n, &m);
Start = 0, End = n+m+1;
int i, ind = 0;
memset(p, -1, sizeof(p));
for (i = 1; i <= n; ++i)
{
e[ind].v = i;
e[ind].cost = 1;
e[ind].next = p[Start];
p[Start] = ind++;
e[ind].v = Start;
e[ind].cost = 0;
e[ind].next = p[i];
p[i] = ind++;
}
for (i = 1; i <= m; ++i)
{
e[ind].v = End;
e[ind].cost = 1;
e[ind].next = p[i+n];
p[i+n] = ind++;
e[ind].v = i+n;
e[ind].cost = 0;
e[ind].next = p[End];
p[End] = ind++;
}
for (i = 0; i < k; ++i)
{
int from, to;
scanf("%d %d", &from, &to);
e[ind].v = n + to;
e[ind].cost = 1;
e[ind].next = p[from];
p[from] = ind++;
e[ind].v = from;
e[ind].cost = 0;
e[ind].next = p[to+n];
p[to+n] = ind++;
}
}
int Dinic()
{
int Max_Flow = 0;
while (true)
{
int front = 0, last = 0, i;
for (i = 0; i <= n+m+1; ++i)
{
level[i] = 0;
}
level[Start] = 1;
que_st[front] = Start;
while (front <= last)
{//bfs求层次图
int t = que_st[front++];
for (i = p[t]; i != -1; i = e[i].next)
{
if (e[i].cost && !level[e[i].v])
{
level[e[i].v] = level[t] + 1; que_st[++last] = e[i].v;
}
}
}
if (!level[End])
{//汇点不在层次图内 退出
break;
}
for (i = 0; i <= n+m+1; ++i)
{
q[i] = p[i];
}
last = -1;
while (true)
{//栈模拟dfs 用dfs进行增广
if (last < 0)
{//栈空
for (i = q[Start]; i != -1; i = e[i].next)
{//找与源点相邻的边
if (e[i].cost && q[e[i].v] != -1 && level[e[i].v] == 2)
{
break;
}
}
if (i >= 0)
{
que_st[++last] = i;
q[Start] = e[i].next;
}
else
{//与源点相连的边都被删除
break;
}
}
int u = e[que_st[last]].v; //栈中最后的那个顶点
if (u == End)
{//u为汇点 说明找到增广路
int min = 0XFFFFFFF;
int index = -1;
for (i = 0; i <= last; ++i)
{
if (e[que_st[i]].cost < min)
{//可增广的最大值
min = e[que_st[i]].cost;
index = i;
}
}
Max_Flow += min;
for (i = 0; i <= last; ++i)
{//对增广路进行增广
e[que_st[i]].cost -= min;
e[que_st[i]^1].cost += min;
}
//后退至删边后原增广路中可到达的最远点
last = index - 1;
}
else
{//u不是汇点
for (i = q[u]; i != -1; i = e[i].next)
{//找与u相邻的边
if (e[i].cost && q[e[i].v] != -1 && level[e[i].v] == level[u] + 1)
{
break;
}
}
if (i >= 0)
{//找到 则入栈
que_st[++last] = i;
q[u] = e[i].next;
}
else
{//否则 删除点u和与u相邻的所有边
last--;
q[u] = -1;
}
}
}
}
return Max_Flow;
}
int main()
{
while (scanf("%d", &k) != EOF && k)
{
init();
printf("%d\n", Dinic());
}
return 0;
}