强大的Dinic

来源:互联网 发布:承德县大数据招聘信息 编辑:程序博客网 时间:2024/06/04 22:19
Dinic算相对来讲比较稳定,写成邻接表示最好的选择
这里以hdu 4280 为例子 加入一个开栈的外挂神器
递归版:
struct EDGE
{
int v, w;
int next;
}E[maxn*2];
int head[maxn], level[maxn];
int k;


void addE(int u, int v,int w)
{
E[k].v = v;
E[k].w = w;
E[k].next = head[u];
head[u] = k++;


E[k].v = u;
E[k].w = w;
E[k].next = head[v];
head[v] = k++;
}


bool BFS(int s, int t)//层次网络的索搜和BSF索搜迷宫很像,因为都是一层一层的尽心,最终只要把层次记录就ok了
{
memset(level, 0, sizeof level);
Q<int>q;
q.push(s);
level[s] = 1;
while (!q.empty())
{
int u = q.front(); q.pop();
if (u == t)
return true;
for (int i = head[u]; i != -1; i = E[i].next)
{
int v = E[i].v;
if (!level[v] && E[i].w > 0)
{
level[v] = level[u] + 1;
q.push(v);
}
}
}
return false;
}


int DFS(int u,int maxf,int t)
{
int res = 0;
if (u == t)
return maxf;
for (int i = head[u]; i != -1; i = E[i].next)
{
int v = E[i].v;
if (level[v] == level[u] + 1 && E[i].w > 0)
{
int f = DFS(v, min(maxf - res, E[i].w), t);
E[i].w -= f;
E[i ^ 1].w += f;
res += f;
if (res == maxf)
return res;
}
}
if (res == 0)
level[u] = 0;
return res;
}


void Dinic(int s,int t)
{
int ans = 0;
while (BFS(s, t))
ans += DFS(s, INF_MAX, t);
printf("%d\n", ans);
}




非递归版:
struct Edge
{
int v, f;
int next;
}E[(maxn*2+maxm)*2];
int k;
int head[maxn], level[maxn], h[maxn], stack[maxn];


bool BFS(int s, int t)
{
memset(level, 0, sizeof level);
level[s] = 1;
Q<int>q;
q.push(s);
while (!q.empty())
{
int u = q.front(); q.pop();
if (u == t)
return true;
for (int i = head[u]; i != -1; i = E[i].next)
{
int v = E[i].v;
if (!level[v] && E[i].f>0)
{
level[v] = level[u] + 1;
q.push(v);
}
}
}
return false;
}


void Dinic(int s, int t)
{
int maxflow = 0;
while (BFS(s, t))
{
memcpy(h, head, sizeof h);
int top = 0, u = s;
while (true)
{
if (u == t)
{
int minflow = INF_MAX, flag;
for (int i = 0; i < top; i++)
{
if (minflow>E[stack[i]].f)
{
minflow = E[stack[i]].f;
flag = i;
}
}
for (int i = 0; i < top; i++)
{
E[stack[i]].f -= minflow;
E[stack[i] ^ 1].f += minflow;
}
top = flag;
maxflow += minflow;
u = E[stack[top]^1].v;//反向边的邻接点
}
for (int i = h[u]; i != -1; i = h[u] = E[i].next)
{
int v = E[i].v;
if (level[v] == level[u] + 1 && E[i].f)
break;
}
if (h[u] != -1)
{
stack[top++] = h[u];
u = E[h[u]].v;
}
else
{
if (top == 0)
break;
level[u] = 0;
u = E[stack[--top]^1].v;//反向边的邻接点
}
}
}
printf("%d\n", maxflow);
}


建议用非递归版的比较好,相对来讲性能会快些,而且在杭电不会爆栈式关键
0 0
原创粉丝点击