快速最大流ISAP模板
//By kuangbin
//只能求一次最大流
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
const int MAXN=20010;
const int MAXM=440020;//注意边的数目,因为连边是连两条/经常re
const int INF=0x3f3f3f3f;
using namespace std;
//int n,s,t,N;//输入的顶点数,源点,汇点,总顶点数
struct Edge {
int to,next,cap,flow;
} edge[MAXM<<1];
int head[MAXN],tot,gap[MAXN],d[MAXN],cur[MAXN],que[MAXN],p[MAXN];
void init()
{
tot=0;
memset(head,-1,sizeof(head));
}
void addedge(int u,int v,int c)
{
edge[tot].to = v;
edge[tot].cap = c;
edge[tot].flow = 0;
edge[tot].next = head[u];
head[u] = tot++;
edge[tot].to = u;
edge[tot].cap = 0;
edge[tot].flow = 0;
edge[tot].next = head[v];
head[v] = tot++;
}
void BFS(int source,int sink)
{
memset(d,-1,sizeof(d));//clr(d,-1);
memset(gap,0,sizeof(gap));//clr(gap,0);
gap[0] = 1;
int front = 0,rear = 0;
d[sink] = 0;
que[rear++] = sink;
while(front != rear) {
int u = que[front++];
for(int i = head[u]; i != -1; i = edge[i].next) {
int v = edge[i].to;
if(d[v] != -1) continue;
que[rear++] = v;
d[v] = d[u]+1;
gap[d[v]]++;
}
}
}
int isap(int source,int sink,int N)
{
BFS(source,sink);
memcpy(cur,head,sizeof(head));
int top = 0,x = source,flow = 0;
while(d[source] < N) {
if(x == sink) {
int Min = INF,inser;
for(int i = 0; i < top; ++i) {
if(Min > edge[p[i]].cap - edge[p[i]].flow) {
Min = edge[p[i]].cap - edge[p[i]].flow;
inser = i;
}
}
for(int i = 0; i < top; ++i) {
edge[p[i]].flow += Min;
edge[p[i]^1].flow -= Min;
}
flow += Min;
top = inser;
x = edge[p[top]^1].to;
continue;
}
int ok = 0;
for(int i = cur[x]; i != -1; i = edge[i].next) {
int v = edge[i].to;
if(edge[i].cap > edge[i].flow && d[v]+1 == d[x]) {
ok = 1;
cur[x] = i;
p[top++] = i;
x = edge[i].to;
break;
}
}
if(!ok) {
int Min = N;
for(int i = head[x]; i != -1; i = edge[i].next) {
if(edge[i].cap > edge[i].flow && d[edge[i].to] < Min) {
Min = d[edge[i].to];
cur[x] = i;
}
}
if(--gap[d[x]] == 0) break;
gap[d[x] = Min+1]++;
if(x != source) x = edge[p[--top]^1].to;
}
}
return flow;
}
//这个模板有待商榷
const int maxn= 405;//最大顶点数
const int maxm = 160005;//最大边数
const int INF=0x3f3f3f3f;
using namespace std;
int n,s,t,N;//输入的顶点数,源点,汇点,建图后的总顶点数(判断dis[s]<N)
struct node
{
int to,cap,next,pre;//pre是指互为反向弧
}edges[maxm];
int head[maxn],tot,que[maxn],d[maxn],gap[maxn],cur[maxn],rpath[maxn];
//邻接表,边数,队列,距离标号,间隙优化,当前弧,可增广路上的弧编号
void init(){
tot=0;
memset(head,-1,sizeof(head));
}
void addedge(int u,int v,int c)
{
edges[tot].to=v;
edges[tot].cap=c;
edges[tot].next=head[u];
head[u] = tot ++;
edges[tot-1].pre=tot;
edges[tot].pre = tot-1;
edges[tot].cap = 0;
edges[tot].to = u;
edges[tot].next = head[v];
head[v] = tot ++;
}
void re_Bfs(){
memset(gap,0,sizeof(gap));
memset(d,-1,sizeof(d));
int i,front=0,rear=0;
que[rear ++] = t;
gap[0] = 1;
d[t] = 0;
while(front != rear){
int u = que[front ++];
for(i = head[u];i != -1;i = edges[i].next){
if(edges[edges[i].pre].cap == 0 || d[edges[i].to]!=-1)
continue;
d[edges[i].to] = d[u] + 1;
gap[d[edges[i].to]] ++;
que[rear ++] = edges[i].to;
}
}
}
int ISAP(){
re_Bfs();
memcpy(cur,head,sizeof(head));
int i,u=s,maxflow = 0;
while(d[s] < N){
if(u == t){
int curflow = INF;
for(i = s;i != t;i = edges[cur[i]].to)
curflow = min(curflow,edges[cur[i]].cap);
for(i = s;i != t;i = edges[cur[i]].to){
edges[cur[i]].cap -= curflow;
edges[edges[cur[i]].pre].cap += curflow;
}
maxflow += curflow;
u = s;
}
for(i = cur[u];i != -1;i = edges[i].next)
if(edges[i].cap > 0 && d[edges[i].to] + 1 == d[u])
break;
if(i != -1){
cur[u] = i;
rpath[edges[i].to] = edges[i].pre;
u = edges[i].to;
}
else{
if((-- gap[d[u]]) == 0) break;
cur[u] = head[u];
int Min = N;
for(i = cur[u];i != -1;i = edges[i].next)
if(edges[i].cap > 0)
Min = min(Min,d[edges[i].to]);
gap[d[u]=Min+1] ++;
if(u != s) u = edges[rpath[u]].to;
}
}
return maxflow;
}
Isap//速度好慢的
//注意给源点,汇点,结点总个数n 赋值,最大距离标号的修改
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
const int maxn=210;//最大结点数
const int INF=0x3f3f3f3f;
using namespace std;
int n,s,t,N;//输入的顶点数,源点,汇点,总顶点数
struct Edge{
int from,to,cap,flow;
Edge(int u,int v,int c,int f):from(u),to(v),cap(c),flow(f){}
};
vector<Edge> edges;//边集
vector<int> G[maxn];//顶点集
int gap[maxn],d[maxn],cur[maxn],p[maxn];
//间隙优化,距离标号,当前弧,可增广路上的上一条弧
inline void addedge(int u,int v,int c){
edges.push_back(Edge(u,v,c,0));
edges.push_back(Edge(v,u,0,0));
int m=edges.size();
G[u].push_back(m-2);
G[v].push_back(m-1);
}
int ISAP(int S,int T){
s=S,t=T;//别忘了赋值和修改
memset(cur,0,sizeof(cur));
memset(d,0,sizeof(d));
memset(gap,0,sizeof(gap));
int x=s,flow=0,a=INF;
while(d[s]<N){
if(x==t){
flow+=a;
while(x!=s){
edges[p[x]].flow+=a;
edges[p[x]^1].flow-=a;
x=edges[p[x]].from;
}
a=INF;
}
int ok=0;
for(int i=cur[x];i<G[x].size();++i){
Edge& e=edges[G[x][i]];
if(e.cap>e.flow&&d[e.to]+1==d[x]){
p[e.to]=G[x][i];
cur[x]=i;
x=e.to;
ok=1;
a=min(a,e.cap-e.flow);
break;
}
}
if(!ok){
int m=N;//为
for(int i=0;i<G[x].size();++i){
Edge& e =edges[G[x][i]];
if(e.cap>e.flow) m=min(m,d[e.to]);
}
if(--gap[d[x]]==0) break;
gap[d[x]=m+1]++;
cur[x]=0;
if(x!=s) x=edges[p[x]].from;
}
}
return flow;
}
————————————————————————————
Dinic
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<queue>
const int maxn=1100;//最大顶点数
const int maxm=1100;//最大边数
const int INF=0x3f3f3f3f;//无穷大
using namespace std;
int n,m,s,t;//输入的顶点数,输入的边数,源点,汇点
struct Edge{
int from,to,cap,flow;
};
vector<Edge> edges;//边集
vector<int> G[maxn];//顶点集
int d[maxn],cur[maxn];
//距离标号,当前弧
bool vis[maxn];//标记数组
inline void addedge(int u,int v,int c){
edges.push_back((Edge){u,v,c,0});
edges.push_back((Edge){v,u,0,0});
int x=edges.size();
G[u].push_back(x-2);
G[v].push_back(x-1);
}
bool BFS(){//构建层次网络
memset(vis,0,sizeof(vis));
queue<int> Q;
Q.push(s);
d[s]=0;
vis[s]=1;
while(!Q.empty()){
int x=Q.front();Q.pop();
for(int i=0;i<G[x].size();++i){
Edge& e=edges[G[x][i]];
if(!vis[e.to]&&e.cap>e.flow){
vis[e.to]=1;
d[e.to]=d[x]+1;
Q.push(e.to);
}
}
}
return vis[t];
}
int DFS(int x,int a){//寻找增广路
if(x==t||a==0) return a;
int flow=0,f;
for(int& i=cur[x];i<G[x].size();++i){
Edge& e=edges[G[x][i]];
if(d[x]+1==d[e.to]&&(f=DFS(e.to,min(a,e.cap-e.flow)))>0){
e.flow+=f;
edges[G[x][i]^1].flow-=f;
flow+=f;
a-=f;
if(a==0) break;
}
}return flow;
}
int Dinic(int S,int T){
s=S,t=T;
int flow=0;
while(BFS()){
memset(cur,0,sizeof(cur));
flow+=DFS(s,INF);
}
return flow;
}