题意:输入m n, m是边数,n是点数。 接下来m行: 起点,终点,容量。求以 1 为源点, n为汇点的最大流。
#include<stdio.h> #include<string.h> #include<queue> #include<algorithm> using namespace std; const int INF = 0xfffffff; const int MAXN = 200 + 10; //邻接矩阵存放图。 int flow[MAXN][MAXN]; //mark[]标记是否访问过,pre[]记录增广路。 int mark[MAXN], pre[MAXN]; int m, n, f; //f为最大流。 void max_flow() { //不断寻找增广路,知道找不到为止,找不到的标志为 mark[n]==0. while(1) { memset(mark, 0, sizeof(mark)); memset(pre, 0, sizeof(pre)); queue<int> Q; mark[1] = 1; Q.push(1); while( !Q.empty() ) { int cnt = Q.front(); Q.pop(); //找到增广路,跳出。 if(cnt == n) { break; } for(int i = 1; i <= n; i++) { if(!mark[i] && flow[cnt][i] > 0) { mark[i] = 1; Q.push(i); pre[i] = cnt; } } } //如果没找到可增广的路,直接跳出. if( !mark[n] ) { break; } //计算该增广路最大可增加的流量. int minx = INF; for(int i = n; i != 1; i = pre[i]) { minx = min( flow[pre[i]][i], minx ); } for(int i = n; i != 1; i = pre[i]) { flow[pre[i]][i] -= minx; //更新正向流量。 flow[i][pre[i]] += minx; //更新反向流量。 } f += minx; } } int main() { while(scanf("%d %d", &m, &n) != EOF) { memset(flow, 0, sizeof(flow)); for(int i = 0; i < m; i++) { int u, v, len; scanf("%d %d %d", &u, &v, &len); //这个题有重边的情况,所以要flow[u][v] += len;直接等于过不去。 flow[u][v] += len; } f = 0; max_flow(); printf("%d\n", f); } return 0; }
时间: 2024-12-13 02:23:03