好题模板http://blog.csdn.net/carryheart/article/details/52470992
摘抄
最快的最大流模板:
#include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #include<string> #include<vector> #include<stack> #include<bitset> #include<cstdlib> #include<cmath> #include<set> #include<list> #include<deque> #include<map> #include<queue> #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 ISAP(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; }
最小费用最大流
/* 最小费用最大流,求最大费用只需要取相反数,结果取相反数即可。 点的总数为 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优化模板
扫描二维码关注公众号,回复:
1453309 查看本文章
#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; }