網路流 最大流 最小割 最小費用流
阿新 • • 發佈:2019-01-06
最大流SAP+GAP
#include <queue> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; const int MAXN = 5010; const int MAXN_INT = (1 << 29); struct Edge{ int v, w, nxt; }; bool isFind; int head[MAXN]; Edge edge[MAXN]; int dis[MAXN], gap[MAXN]; int n, m, ecnt, aug, maxFlow; void init(){ ecnt = maxFlow = 0; memset(gap, 0, sizeof(gap)); memset(dis, 0, sizeof(dis)); memset(edge, 0, sizeof(edge)); memset(head, -1, sizeof(head)); gap[0] = n; } void addEdge(int u, int v, int w){ edge[ecnt].v = v; edge[ecnt].w = w; edge[ecnt].nxt = head[u]; head[u] = ecnt++; } void Find(int s){ int dx, augc, minDis; if(s == n){ isFind = true; maxFlow += aug; return; } augc = aug; minDis = n - 1; for(int i = head[i]; i + 1; i = edge[i].nxt){ if(edge[i].w > 0){ if(dis[s] == dis[edge[i].v] + 1){ aug = min(aug, edge[i].w); Find(edge[i].v); if(dis[1] >= n) return; if(isFind){ dx = i; break; } aug = augc; } minDis = min(minDis, dis[edge[i].v]); } } if(!isFind){ gap[dis[s]]--; if(gap[dis[s]] == 0) dis[1] = n; dis[s] = minDis + 1; gap[dis[s]]++; }else{ edge[dx].w -= aug; edge[dx ^ 1].w += aug; } } int main(){ while(scanf("%d%d", &n, &m) != EOF){ init(); int u, v, w; for(int i = 0; i < m; i++){ scanf("%d%d%d", &u, &v, &w); addEdge(u, v, w); addEdge(v, u, 0); } while(dis[1] < n){ isFind = 0; aug = MAXN_INT; Find(1); } cout << maxFlow << endl; } return 0; }
最大流預流推進
const int size = 501; const int MAX = 1 << 15; int graph[size][size]; int label[size]; //標號 bool visited[size]; bool bfs(int st, int ed) { memset(label, -1, sizeof(label)); memset(visited, false, sizeof(visited)); label[st] = 0; visited[st] = true; vector < int >plist; plist.push_back(st); while (plist.size()) { int p = plist[0]; plist.erase(plist.begin()); for (int i = 0; i < size; i++) { if (graph[i][p] > 0 && !visited[i]) { plist.push_back(i); visited[i] = true; label[i] = label[p] + 1; } } } if (label[ed] == -1) { return false; } return true; } int inflow[size]; //流入量 int maxFlow() { memset(inflow, 0, sizeof(inflow)); //hights bfs(size - 1, 0); //end point: size - 1, start point: 0 memset(visited, false, sizeof(visited)); //prepare() vector < int >plist; for (int i = 0; i < size; i++) { if (graph[start][i] > 0) { inflow[i] = graph[start][i]; graph[start][i] -= inflow[i]; graph[i][start] += inflow[i]; if (!visited[i]) { plist.push_back(i); visited[i] = true; } } } while (plist.size()) { int p = plist[0]; plist.erase(plist.begin()); visited[p] = false; int minLabel = -1; for (int i = 0; i < size; i++) { if (graph[p][i] > 0) { if (label[p] == label[i] + 1) { int flow = min(inflow[p], graph[p][i]); inflow[p] -= flow; inflow[i] += flow; graph[p][i] -= flow; graph[i][p] += flow; if (!visited[i] && inflow[i] > 0) { plist.push_back(i); visited[i] = true; } } } } if (inflow[p] > 0 && p != end) { for (int i = 0; i < size; i++) { if (graph[p][i] > 0) { if (minLabel == -1 || minLabel > label[i] + 1) { minLabel = label[i] + 1; } } } if (!visited[p] && minLabel != -1 && minLabel < size) //minLabel < size, 這個條件需要加上, 因為經過測試發現有死迴圈的可能 { for (int i = 0; i < size; i++) { if (label[i] + 1 == minLabel && graph[p][i] > 0) { visited[p] = true; label[p] = minLabel; plist.push_back(p); break; } } } } } return inflow[end]; }
最小費用最大流
#include <queue> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; const int MAXN = 1010; const int MAXM = 1000100; const int MAXN_INT = (1 << 29); struct Edge{ int v, w, c, nxt; }; struct Node{ int id, v; }; bool vis[MAXN]; Node pre[MAXN]; Edge edge[MAXN]; int n, m, ecnt, sumFlow; int head[MAXN], dis[MAXN]; void init(){ ecnt = 0; memset(edge, 0, sizeof(edge)); memset(head, -1, sizeof(head)); } void addEdge(int u, int v, int c, int w){ edge[ecnt].v = v; edge[ecnt].w = w; edge[ecnt].c = c; edge[ecnt].nxt = head[u]; head[u] = ecnt++; } bool SPFA(int s, int t, int n){ queue <int> que; memset(vis, 0, sizeof(vis)); fill(dis, dis + MAXN, MAXN_INT); vis[s] = true; dis[s] = 0; que.push(s); while(!que.empty()){ int u =que.front(); que.pop(); vis[u] = false; for(int i = head[u]; i + 1; i = edge[i].nxt){ int v = edge[i].v; if(edge[i].c && dis[v] > dis[u] + edge[i].c){ dis[v] = dis[u] + edge[i].c; pre[v].v = u; pre[v].id = i; if(!vis[v]){ que.push(v); vis[v] = true; } } } } if(dis[t] == MAXN_INT) return false; return true; } int MCMF(int s, int t, int n){ int flow = 0; int minCost = 0; while(SPFA(s, t, n)){ int minFlow = MAXN_INT + 1; for(int i = t; i != s; i = pre[i].v){ minFlow = min(minFlow, edge[pre[i].id].w); } for(int i = t; i != s; i = pre[i].v){ edge[pre[i].id].w -= minFlow; edge[pre[i].id ^ 1].w += minFlow; } minCost += dis[t] * minFlow; } sumFlow = flow; return minCost; } int main(){ while(scanf("%d%d", &n, &m) != EOF){ int u, v, c, w; for(int i = 0; i < m; i++){ scanf("%d%d%d%d", &u, &v, &c, &w); addEdge(u, v, c, w); addEdge(v, u, -c, 0); } int ans = MCMF(1, n, n); printf("%d\n", ans); } return 0; }