最大流
#include <iostream> #include <fstream> #include <cstring> using namespace std; const int MAXN=20010;//点数的最大值 const int MAXM=880010;//边数的最大值 const int INF=0x3f3f3f3f; struct Node { int from,to,next; int cap; }edge[MAXM]; int tol; int head[MAXN]; int dis[MAXN]; int gap[MAXN];//gap[x]=y :说明残留网络中dis[i]==x的个数为y int n;//n是总的点的个数,包括源点和汇点 void init() { //tol 记录添加的总边数 tol=0; memset(head, -1, sizeof(head)); } void addedge(int u,int v,int w) { //添加前向边 //from u to v 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(dis, -1, sizeof(dis)); memset(gap, 0, sizeof(gap)); gap[0] = 1; dis[end] = 0; int queue[MAXN]; int front, rear; front = rear = 0; queue[rear++] = end; //这里应该是s吧???? //front 和 rear +1之后都需要判断一下是否等于maxn, 如果是则front 或 rear = 0 while(front != rear) { int u = queue[front++]; if(front == MAXN) front = 0; for(int i = head[u]; i != -1; i = edge[i].next) { int v = edge[i].to; if(dis[v] != -1) //表示已标记过 continue; queue[rear++] = v; if(rear == MAXN) rear = 0; dis[v] = dis[u]+1; ++gap[dis[v]]; //距离为dis[v]的点的个数 } } } int SAP(int start,int end) { int res = 0; //存储距离 //用bfs绘制距离图 BFS(start, end); int cur[MAXN]; //存储一条弧 int pre[MAXN]; int top = 0; // top是当前增广路中最前面一个点。 //将head存储的最后一条弧作为初始弧,在此基础上寻找增广边 memcpy(cur, head, sizeof(head)); int u = start; int i; while(dis[start] < n) { if(u == end) //如果找到了一个流,则在剩余网络中查找增广路 { int temp = INF; int inser; //寻找一条增广路,并记录下最小的权值 for(i = 0; i < top; i++) if(temp > edge[pre[i]].cap) { temp = edge[pre[i]].cap; inser = i; } //前向边全部-temp, 后向边+temp for(i = 0; i < top; i++) { edge[pre[i]].cap -= temp; edge[pre[i]^1].cap += temp; } res += temp; top = inser; u = edge[pre[top]].from; } if(u != end && gap[dis[u]-1] == 0)//出现断层,无增广路 break; //找到下一个编号 for(i = cur[u]; i != -1;i = edge[i].next) if(edge[i].cap != 0 && dis[u] == dis[edge[i].to]+1) break; if(i != -1) //如果没有找到容许弧 { cur[u] = i; pre[top++] = i; //向pre中加了一条边,且 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 > dis[edge[i].to]) { min = dis[edge[i].to]; cur[u] = i; } } --gap[dis[u]]; dis[u] = min+1; ++gap[dis[u]]; if(u != start) u = edge[pre[--top]].from; } } return res; } int main(void) { // freopen("1.txt", "r", stdin); int m; while(cin>>m>>n) { tol = 0; memset(head, -1, sizeof(head)); for(int i = 0;i < m;i++) { int a, b, c; cin>>a>>b>>c; addedge(a, b, c); } cout<<SAP(1, n)<<endl; } }