poj1459SAP最大流模板题
最大流建图是关键,将一个题目转化为最大流,要有清晰的建图思想。
这道题注意构建源点和汇点,然后直接套模板。
#include<cstdio> #include<cstring> #include<iostream> using namespace std; const int maxn = 220; const int inf = 10000000;//不要开太大 int c[maxn][maxn]; int q[maxn], pre[maxn]; int level[maxn], gap[maxn]; int n, m, np, nc; int s, t; void init_sap(){ memset(level, 10, sizeof (level)); //printf("--- %d\n", level[2]); //for(int i = 0; i <= n; i ++) level[i] = n + 310; memset(gap, 0, sizeof gap); memset(pre, -1, sizeof pre); int qs = 0, qe = 0; q[qe++] = t; level[t] = 0; gap[ level[t] ] ++; while(qs < qe){ int hd = q[qs++]; for(int i = 1; i <= n; i ++){ if(level[i] > n && c[i][hd] > 0){//level[i] >= n 也可以,why ? q[qe++] = i; level[i] = level[hd] + 1; gap[ level[i] ] ++; } } } } int find_path(int u){ for(int i = 1; i <= n; i ++) if(c[u][i] > 0 && level[u] == level[i] + 1) return i; return -1; } int relabel(int u){ int tmp = inf; for(int i = 1; i <= n; i ++) if(c[u][i] > 0 && tmp > level[i] + 1) tmp = level[i] + 1; if(tmp == inf) tmp = n; return tmp; } int sap(){ init_sap(); int flow = 0, u = s; while(level[s] <= n){ int v = find_path(u); if(v > 0){ pre[v] = u; u = v; if(u == t){ int min_flow = inf; for(int i = t; i != s; i = pre[i]) if(min_flow > c[ pre[i]][i]) min_flow = c[ pre[i]][i]; for(int i = t; i != s; i = pre[i]){ c[pre[i]][i] -= min_flow; c[i][pre[i]] += min_flow; } flow += min_flow; u = s; } }else{ if(-- gap[ level[u]] == 0) return flow; int v = relabel(u); gap[v] ++; level[u] = v; if(u != s) u = pre[u]; } } return flow; } int main(){ while(~scanf("%d%d%d%d", &n, &np, &nc,& m)){ memset(c, 0, sizeof c); s=n+1,t=n+1+1,n+=2; //cout<<s<<endl; for(int i = 1; i <= m; i ++){ int u, v, w; scanf(" (%d,%d)%d", &u, &v, &w); c[u+1][v+1] += w; } for(int i = 1; i <= np; i ++) { int v, w; scanf(" (%d)%d", &v, &w); c[s][v+1] = w; } for(int i = 1; i <=nc; i ++){ int u, w; scanf(" (%d)%d", &u, &w); c[u+1][t] = w; } /*for(int i=1;i<=n;i++) { cout<<endl; for(int j=1;j<=n;j++) cout<<c[i][j]<<' '; }*/ int flow = sap(); printf("%d\n", flow); } return 0; }