题目
思路
预流推进板子。
Dinic,EK,FF都是同一种思想,即撤销,该算法也不例外,不过该算法的思想是和ISAP一样引入高度的概念,在过程中对于每个节点把流堆满,每个点里存了超额流,只要网络中只有s,t的超额流不为0,即为一组解。
code:
#include<iostream>
#include<stack>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<set>
#include<vector>
#include<list>
#include<map>
#include<queue>
#include<deque>
#define inf 0x3f3f3f3f
using namespace std;
int x,y,w;
struct f{
int to,net,w;
} a[2000016];
int head[10001],gap[10001],h[10001],cel[10001];
bool vis[10001];
int n,m,s,t,tot;
struct cmp{
bool operator ()(int x,int y)const
{
return h[x]<h[y];
}
};
priority_queue<int,vector<int>,cmp > u;
queue<int> p;
void add(int x,int y,int w)
{
a[tot].to=y;
a[tot].w=w;
a[tot].net=head[x];
head[x]=tot;
tot++;
return;
}
bool bfs()
{
memset(h+1,inf,sizeof(int)*n);
h[t]=0;
p.push(t);
while (p.size())
{
int o=p.front();
p.pop();
for (int i=head[o];i!=-1;i=a[i].net)
{
if (a[i^1].w!=0&&h[a[i].to]>h[o]+1)
{
h[a[i].to]=h[o]+1;
p.push(a[i].to);
}
}
}
return h[s]!=inf;
}
void push(int x)
{
for (int i=head[x];i!=-1;i=a[i].net)
{
if (a[i].w&&h[x]==h[a[i].to]+1)
{
int temp=min(cel[x],a[i].w);
a[i].w-=temp;
a[i^1].w+=temp;
cel[x]-=temp;
cel[a[i].to]+=temp;
if (a[i].to!=s&&a[i].to!=t&&vis[a[i].to]==0)
{
vis[a[i].to]=1;
u.push(a[i].to);
}
}
if (cel[x]==0) break;
}
return;
}
void relabel(int x)
{
h[x]=inf;
for (int i=head[x];i;i=a[i].net)
{
if (a[i].w!=0&&h[a[i].to]+1<h[x]) h[x]=h[a[i].to]+1;
}
return;
}
int hlpp()
{
if (!bfs()) return 0;
h[s]=n;
memset(gap,0,sizeof(int)*(n<<1));
for (int i=1;i<=n;i++) if (h[i]!=inf) gap[h[i]]++;
for (int i=head[s];i!=-1;i=a[i].net)
{
if (a[i].w)
{
int temp=a[i].w;
a[i].w-=temp;
a[i^1].w+=temp;
cel[s]-=temp;
cel[a[i].to]+=temp;
if (a[i].to!=s&&a[i].to!=t&&vis[a[i].to]==0)
{
vis[a[i].to]=1;
u.push(a[i].to);
}
}
}
while (u.size())
{
int o=u.top();
u.pop();
vis[o]=0;
push(o);
if (cel[o])
{
gap[h[o]]--;
if (!gap[h[o]])
{
for (int i=1;i<=n;i++)
{
if (i!=s&&i!=t&&h[i]>h[o]&&h[i]<n+1) h[i]=n+1;
}
}
relabel(o);
gap[h[o]]++;
u.push(o);
vis[o]=1;
}
}
return cel[t];
}
signed main()
{
scanf("%d%d%d%d",&n,&m,&s,&t);
memset(head,-1,sizeof(head));
for (int i=1;i<=m;i++)
{
long long w;
scanf("%d%d%lld",&x,&y,&w);
add(x,y,w);
add(y,x,0);
}
long long uu=hlpp();
printf("%lld",uu);
return 0;
}