ddwqwq @ 2017-12-24 13:51:33
最开始用EK,360多ms,改用一般预留推送变成800ms,现在改用更优的前置-重贴标签算法,三个RE70分
难道更快的算法不如EK皮实,经不起我糟蹋?
大家帮忙看看吧
#include <cstdlib>
#include <iostream>
#include <cstdio>
#include <math.h>
#include <cstring>
using namespace std;
struct node {
int aim;
int w;
node *next;
};
struct Node {
int v;
Node *next;
Node *last;
};
int S, T;
int N, M, X;
int c[250000], e[20005], h[20005], c_size;
node *head[20005], *cur[20005];
void add(node *&head, int aim, int w)
{
node *p = new(node);
p->next = NULL;
p->aim = aim;
p->w = c_size;
c[c_size++] = w;
if (head == NULL)
head = p;
else
{
p->next = head;
head = p;
}
}
int min(int a, int b)
{
if (a < b)
return a;
return b;
}
void prepare(int s)
{
h[s] = N;
node *p = head[s];
while (p != NULL)
{
if (c[p->w] > 0)
{
int w = c[p->w];
e[p->aim] += w;
c[p->w] = 0;
c[p->w ^ 1] += w;
}
p = p->next;
}
}
void push(int u, node *p)
{
if (e[u] > 0 && c[p->w] > 0 && h[u] == h[p->aim] + 1)
{
int w = min(c[p->w], e[u]);
c[p->w] -= w;
c[p->w ^ 1] += w;
e[u] -= w;
e[p->aim] += w;
}
}
void relable(int v)
{
int i = 99999999;
node *p = head[v];
while (p != NULL)
{
if (c[p->w] > 0)
{
i = min(i, h[p->aim]);
}
p = p->next;
}
h[v] = i + 1;
}
void discharge(int v)
{
while (e[v] > 0)
{
node *p = cur[v];
if (p == NULL)
{
relable(v);
cur[v] = head[v];
}
else if (c[p->w] > 0 && h[v] == h[p->aim] + 1)
push(v, p);
else
cur[v] = p->next;
}
}
void addNode(Node *&head, int v)
{
Node *p = new(Node);
p->v = v;
p->next = NULL;
p->last = NULL;
if (head == NULL)
head = p;
else
{
p->next = head;
head->last = p;
head = p;
}
}
void relable_to_front()
{
prepare(S);
Node *L = NULL;
int i;
for (i = 1; i <= N; i++)
if (i != S&&i != T)
{
addNode(L, i);
cur[i] = head[i];
}
Node *p = L;
while (p != NULL)
{
int old_h = h[p->v];
discharge(p->v);
if (h[p->v] > old_h)
{
addNode(L, p->v);
if (p->last != NULL)
p->last->next = p->next;
if (p->next != NULL)
p->next->last = p->last;
delete(p);
p = L;
}
p = p->next;
}
}
int main()
{
// freopen("C:/Users/david/Desktop/testdata.in", "r", stdin);
// freopen("C:/Users/david/Desktop/test.out", "w", stdout);
int i, x, y, C;
scanf("%d %d %d %d", &N, &M, &S, &T);
for (i = 0; i < M; i++)
{
scanf("%d %d %d", &x, &y, &C);
add(head[x], y, C);
add(head[y], x, 0);
}
relable_to_front();
printf("%d", e[T]);
// system("pause");
return 0;
}
by SeKong @ 2017-12-24 14:04:05
并不是,我EK,DINIC,ISAP跑的都比你快,ISAP只要20ms,EK和Dinic也只是100ms左右
by _rqy @ 2017-12-24 15:14:28
嗯,Dinic和ISAP时间复杂度都很松qwq...
但是前置重贴标签的时间复杂度是紧的