好题模板http://blog.csdn.net/carryheart/article/details/52470992
摘抄
最大流模板:
#include<iostream>
#include<cmath>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<queue>
using namespace std;
#define ll long long
const int inf=1e9;
const int maxE = 200010;
const int maxN = 5005;
const int maxQ = 10000;
struct Edge{
int to, c, next;
};
Edge edge[maxE];
int head[maxN], cnt;
int dis[maxN], num[maxN], cur[maxN], pre[maxN];
int s, t, nv,p;
int n,m;
int a[maxN][maxN];
int path[maxE][3];
void add(int u, int v, int c){
edge[cnt].to= v; edge[cnt].c = c; edge[cnt].next = head[u]; head[u] = cnt++;
edge[cnt].to = u; edge[cnt].c = 0; edge[cnt].next = head[v]; head[v] = cnt++;
}
void bfs()
{
queue<int>q;
memset(dis,-1,sizeof(dis));
memset(num,0,sizeof(num));
while(!q.empty()) q.pop();
dis[t] = 0;
q.push(t);
while(!q.empty()){
int u = q.front();
q.pop();
for(int i=head[u];i!=-1;i=edge[i].next){
int v=edge[i].to;
if(dis[v]==-1){
dis[v]=dis[u]+1;
num[dis[v]]++;
q.push(v);
}
}
}
}
int ISAP(){
memcpy(cur,head,sizeof(head));
bfs();
int flow = 0, u = pre[s] = s, i;
while(dis[s] < nv){
if(u==t){
int f = inf, neck;
for(i = s; i != t; i = edge[cur[i]].to){
if(f > edge[cur[i]].c){
f = edge[cur[i]].c;
neck = i;
}
}
for(i = s; i != t; i = edge[cur[i]].to){
edge[cur[i]].c -= f;
edge[cur[i] ^ 1].c += f;
}
flow += f;
u = neck;
}
for(i = cur[u]; ~i; i = edge[i].next) if(edge[i].c &&dis[u] == dis[edge[i].to] + 1) break;
if(~i){
cur[u] = i;
pre[edge[i].to] = u;
u = edge[i].to;
}
else{
if(0 == (--num[dis[u]])) break;
int mind = nv;
for(i = head[u]; ~i; i = edge[i].next){
if(edge[i].c && mind > dis[edge[i].to]){
mind = dis[edge[i].to];
cur[u] = i;
}
}
dis[u] = mind + 1;
num[dis[u]]++;
u = pre[u];
}
}
return flow;
}
最小费用最大流
/*
最小费用最大流,求最大费用只需要取相反数,结果取相反数即可。
点的总数为 N,点的编号 0~N-1
*/
const int MAXN = 10000;
const int MAXM = 100000;
const int INF = 0x3f3f3f3f;
struct Edge
{
int to,next,cap,flow,cost;
} edge[MAXM];
int head[MAXN],tol;
int pre[MAXN],dis[MAXN];
bool vis[MAXN];
int N;//节点总个数,节点编号从0~N-1
void init(int n)
{
N = n;
tol = 0;
memset(head,-1,sizeof (head));
}
void addedge (int u,int v,int cap,int cost)
{
edge[tol].to = v;
edge[tol].cap = cap;
edge[tol].cost = cost;
edge[tol].flow = 0;
edge[tol].next = head[u];
head[u] = tol++;
edge[tol].to = u;
edge[tol].cap = 0;
edge[tol].cost = -cost;
edge[tol].flow = 0;
edge[tol].next = head[v];
head[v] = tol++;
}
bool spfa(int s,int t)
{
queue<int>q;
for(int i = 0; i < N; i++)
{
dis[i] = INF;
vis[i] = false;
pre[i] = -1;
}
dis[s] = 0;
vis[s] = true;
q.push(s);
while(!q.empty())
{
int u = q.front();
q.pop();
vis[u] = false;
for(int i = head[u]; i != -1; i = edge[i]. next)
{
int v = edge[i]. to;
if(edge[i].cap > edge[i].flow &&
dis[v] > dis[u] + edge[i]. cost )
{
dis[v] = dis[u] + edge[i]. cost;
pre[v] = i;
if(!vis[v])
{
vis[v] = true;
q.push(v);
}
}
}
}
if(pre[t] == -1)return false;
else return true;
}
//返回的是最大流,cost存的是最小费用
int minCostMaxflow(int s,int t,int &cost)
{
int flow = 0;
cost = 0;
while(spfa(s,t))
{
int Min = INF;
for(int i = pre[t]; i != -1; i = pre[edge[i^1].to])
{
if(Min > edge[i].cap - edge[i]. flow)
Min = edge[i].cap - edge[i].flow;
}
for(int i = pre[t]; i != -1; i = pre[edge[i^1].to])
{
edge[i].flow += Min;
edge[i^1].flow -= Min;
cost += edge[i]. cost * Min;
}
flow += Min;
}
return flow;
}
Dinic优化模板
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#define INF 0x7fffffff
#define maxn 25000
using namespace std;
struct Edge{
int from,to,cap,flow;
};
class Dinic{
private:
int s,t,c;
vector<Edge>edges;
vector<int>G[maxn];//结点
bool vis[maxn];
int dist[maxn];
int cur[maxn];
public:
int n,m;
void AddEdge(int from,int to,int cap){
edges.push_back((Edge){from,to,cap,0});
edges.push_back((Edge){to,from,0,0});
c=edges.size();
G[from].push_back(c-2);
G[to].push_back(c-1);
}
bool BFS(){
queue<int>Q;
memset(vis,0,sizeof(vis));
Q.push(s);
dist[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;
dist[e.to]=dist[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(dist[x]+1==dist[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 Maxflow(int s,int t){
this->s=s;this->t=t;
int flow=0;
while(BFS()){
memset(cur,0,sizeof(cur));
flow+=DFS(s,INF);
flow+=DFS(s,INF);
}
return flow;
}
void init(){
edges.clear();
for(int i=0;i<maxn;i++){
G[i].clear();
dist[i]=0;
}
}
vector<int> Mincut(){
BFS();
vector<int> ans;
for(int i=0;i<edges.size();i++){
Edge& e=edges[i];
if(vis[e.from]&&!vis[e.to]&&e.cap>0)ans.push_back(i);
}
return ans;
}
}Do;
Dinic优化模板
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <queue>
using namespace std;
#define inf 0x7fffffff
struct Edge{
int v,w,nxt;
}g[1001];
int head[1001];
int cnt;
void addEdge(int u,int v,int w){
g[cnt].v = v;
g[cnt].w = w;
g[cnt].nxt = head[u];
head[u] = cnt;
++ cnt;
}
int n,m,x,y,z;
int ans,flow;
int dis[1001];
queue<int> q;
int S,T;
void init(){
memset(head,-1,sizeof(head));
memset(g,0,sizeof(g));
cnt = 0;
memset(dis,-1,sizeof(dis));
while(!q.empty()) q.pop();
ans = 0;
}
int bfs(){
memset(dis,-1,sizeof(dis));
while(!q.empty()) q.pop();
dis[S] = 0;
q.push(S);
while(!q.empty()){
int u = q.front();
q.pop();
for(int i=head[u];i!=-1;i=g[i].nxt){
int v = g[i].v;
if(dis[v]==-1 && g[i].w > 0){
dis[v] = dis[u] + 1;
q.push(v);
}
}
}
return dis[T]!=-1;
}
int dfs(int u,int exp){
if(u==T) return exp;
int flow=0,tmp= 0;
for(int i=head[u];i!=-1;i=g[i].nxt){
int v = g[i].v;
if((dis[v] == (dis[u]+1)) && (g[i].w>0)){
tmp = dfs(v,min(exp,g[i].w));
if(!tmp) continue;
exp -= tmp;
flow += tmp;
g[i].w -= tmp;
g[i^1].w += tmp;
if(!exp) break;
}
}
return flow;
}
int main(){
while(~scanf("%d%d",&m,&n)){
init();
S = 1;T = n;
for(int i=1;i<=m;++i){
scanf("%d%d%d",&x,&y,&z);
addEdge(x,y,z);
addEdge(y,x,0);
}
while(bfs()){
ans += dfs(S,inf);
}
printf("%d\n",ans);
}
}
Dinic优化模板
class Graph
{
private:
int cnt;
int Head[maxN];
int Next[maxM];
int W[maxM];
int V[maxM];
int Depth[maxN];
int cur[maxN];//cur就是记录当前点u循环到了哪一条边
public:
int s,t;
void init()
{
cnt=-1;
memset(Head,-1,sizeof(Head));
memset(Next,-1,sizeof(Next));
}
void _Add(int u,int v,int w)
{
cnt++;
Next[cnt]=Head[u];
Head[u]=cnt;
V[cnt]=v;
W[cnt]=w;
}
void Add_Edge(int u,int v,int w)
{
_Add(u,v,w);
_Add(v,u,0);
}
int dfs(int u,int flow)
{
if (u==t)
return flow;
for (int& i=cur[u];i!=-1;i=Next[i])//注意这里的&符号,这样i增加的同时也能改变cur[u]的值,达到记录当前弧的目的
{
if ((Depth[V[i]]==Depth[u]+1)&&(W[i]!=0))
{
int di=dfs(V[i],min(flow,W[i]));
if (di>0)
{
W[i]-=di;
W[i^1]+=di;
return di;
}
}
}
return 0;
}
int bfs()
{
queue<int> Q;
while (!Q.empty())
Q.pop();
memset(Depth,0,sizeof(Depth));
Depth[s]=1;
Q.push(s);
do
{
int u=Q.front();
Q.pop();
for (int i=Head[u];i!=-1;i=Next[i])
if ((Depth[V[i]]==0)&&(W[i]>0))
{
Depth[V[i]]=Depth[u]+1;
Q.push(V[i]);
}
}
while (!Q.empty());
if (Depth[t]>0)
return 1;
return 0;
}
int Dinic()
{
int Ans=0;
while (bfs())
{
for (int i=1;i<=n;i++)//每一次建立完分层图后都要把cur置为每一个点的第一条边 感谢@青衫白叙指出这里之前的一个疏漏
cur[i]=Head[i];
while (int d=dfs(s,inf))
{
Ans+=d;
}
}
return Ans;
}
};
ISAP:
#define MAXN 100010 //点
#define MAXM 800010//边
#define inf 0x3f3f3f
using namespace std;
struct Node
{
int from,to,next;
int cap;
}edge[MAXM];
int tol;
int head[MAXN];
int dep[MAXN];
int gap[MAXN];//gap[x]=y :说明残留网络中dep[i]==x的个数为y
int n;//n是总的点的个数,包括源点和汇点
void init()
{
tol=0;
memset(head,-1,sizeof(head));
}
void addedge(int u,int v,int w)
{
edge[tol].from=u;
edge[tol].to=v;
edge[tol].cap=w;
edge[tol].next=head[u];
head[u]=tol++;
edge[tol].from=v;
edge[tol].to=u;
edge[tol].cap=0;
edge[tol].next=head[v];
head[v]=tol++;
}
void BFS(int start,int end)
{
memset(dep,-1,sizeof(dep));
memset(gap,0,sizeof(gap));
gap[0]=1;
int que[MAXN];
int front,rear;
front=rear=0;
dep[end]=0;
que[rear++]=end;
while(front!=rear)
{
int u=que[front++];
if(front==MAXN)front=0;
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].to;
if(dep[v]!=-1)continue;
que[rear++]=v;
if(rear==MAXN)rear=0;
dep[v]=dep[u]+1;
++gap[dep[v]];
}
}
}
int SAP(int start,int end)
{
int res=0;
BFS(start,end);
int cur[MAXN];
int S[MAXN];
int top=0;
memcpy(cur,head,sizeof(head));
int u=start;
int i;
while(dep[start]<n)
{
if(u==end)
{
int temp=inf;
int inser;
for(i=0;i<top;i++)
if(temp>edge[S[i]].cap)
{
temp=edge[S[i]].cap;
inser=i;
}
for(i=0;i<top;i++)
{
edge[S[i]].cap-=temp;
edge[S[i]^1].cap+=temp;
}
res+=temp;
top=inser;
u=edge[S[top]].from;
}
if(u!=end&&gap[dep[u]-1]==0)//出现断层,无增广路
break;
for(i=cur[u];i!=-1;i=edge[i].next)
if(edge[i].cap!=0&&dep[u]==dep[edge[i].to]+1)
break;
if(i!=-1)
{
cur[u]=i;
S[top++]=i;
u=edge[i].to;
}
else
{
int min=n;
for(i=head[u];i!=-1;i=edge[i].next)
{
if(edge[i].cap==0)continue;
if(min>dep[edge[i].to])
{
min=dep[edge[i].to];
cur[u]=i;
}
}
--gap[dep[u]];
dep[u]=min+1;
++gap[dep[u]];
if(u!=start)u=edge[S[--top]].from;
}
}
return res;
}