网络流 最大流SAPkuangbin模板
hdu 1532 求1~n的最大流
#include<stdio.h> #include<string.h> #include<algorithm> #include<iostream> using namespace std; const int MAXN = 210; //点数的最大值 const int MAXM = 210; //边数的最大值 const int INF = 0x3f3f3f3f; 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; } int main() { // freopen("in.txt","r",stdin); // freopen("out.txt","w",stdout); int start, end; int m; int u, v, z; int T; while (~scanf("%d%d", &m, &n)) { init(); while (m--) { scanf("%d%d%d", &u, &v, &z); addedge(u, v, z); //addedge(v, u, z); } //n一定是点的总数,这是使用SAP模板需要注意的 int ans = SAP(1, n); printf("%d\n", ans); } return 0; }
hdu 4280 给你岛的坐标求最西边到最东边的最大流
/* 最大流模板 sap */ #include<stdio.h> #include<string.h> #include<algorithm> #include<iostream> using namespace std; const int MAXN=100010;//点数的最大值 const int MAXM=400010;//边数的最大值 const int INF=0x3f3f3f3f; 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; } int main() { // freopen("in.txt","r",stdin); // freopen("out.txt","w",stdout); int start,end; int m; int u,v,z; int T; scanf("%d",&T); while(T--) { init(); scanf("%d%d",&n,&m); int minx=10000000; int maxx=-10000000; int x,y; for(int i=1;i<=n;i++) { scanf("%d%d",&x,&y); if(minx>x) { minx=x; start=i; } if(maxx<x) { maxx=x; end=i; } } while(m--) { scanf("%d%d%d",&u,&v,&z); addedge(u,v,z); addedge(v,u,z); } //n一定是点的总数,这是使用SAP模板需要注意的 int ans=SAP(start,end); printf("%d\n",ans); } return 0; }