EK + dijkstra (2246ms) 开氧气(586ms)
dijkstra的势 可以处理负权 https://www.luogu.org/blog/28007/solution-p3381
#include <bits/stdc++.h> using namespace std; const int INF = 1e9; int n, m, s, t, cnt; struct node { int to, nex, val, cost; }E[100005]; int head[5005]; void addedge(int x, int y, int va, int cos) { E[++cnt].to = y; E[cnt].nex = head[x]; head[x] = cnt; E[cnt].val = va; E[cnt].cost = cos; } struct no1 { int to, edge; }pre[5005]; struct no2 { int d, id; friend bool operator < (no2 A, no2 B) { return A.d > B.d; } }; int dis[5005]; int h[5005]; bool dij() { for(int i = 1; i <= n; i++) dis[i] = INF; priority_queue<no2> que; dis[s] = 0; que.push((no2){0, s}); while(!que.empty()) { no2 u = que.top(); que.pop(); if(dis[u.id] < u.d) continue; for(int i = head[u.id]; i; i = E[i].nex) { int v = E[i].to; if(E[i].val > 0 && dis[v] + h[v] > dis[u.id] + E[i].cost + h[u.id]) { dis[v] = dis[u.id] + E[i].cost + h[u.id] - h[v]; pre[v].to = u.id; pre[v].edge = i; que.push((no2){dis[v], v}); } } } if(dis[t] != INF) return true; else return false; } int ans, cos1; void EK() { ans = cos1 = 0; while(dij()) { int mi = INF; for(int i = t; i != s; i = pre[i].to) { mi = min(mi, E[pre[i].edge].val); } for(int i = t; i != s; i = pre[i].to) { E[pre[i].edge].val -= mi; E[pre[i].edge ^ 1].val += mi; } for(int i = 1; i <= n; i++) h[i] += dis[i]; ans += mi; cos1 += mi * h[t]; } } int main() { scanf("%d%d%d%d", &n, &m, &s, &t); cnt = 1; for(int i = 1; i <= m; i++) { int a, b, c, d; scanf("%d%d%d%d", &a, &b, &c, &d); addedge(a, b, c, d); addedge(b, a, 0, -d); } EK(); printf("%d %d ", ans, cos1); return 0; }
EK + spfa (1775ms) 开氧气(1398ms)
#include <bits/stdc++.h> using namespace std; const int INF = 1e9; int n, m, s, t, cnt; struct node { int to, nex, val, cost; }E[100005]; int head[5005]; void addedge(int x, int y, int va, int cos) { E[++cnt].to = y; E[cnt].nex = head[x]; head[x] = cnt; E[cnt].val = va; E[cnt].cost = cos; } struct no1 { int to, edge; }pre[5005]; int dis[5005]; int vis[5005]; bool spfa() { memset(vis, 0, sizeof(vis)); memset(dis, 0x3f, sizeof(dis)); queue<int> que; que.push(s); vis[s] = 1; dis[s] = 0; while(!que.empty()) { int u = que.front(); vis[u] = 0; que.pop(); for(int i = head[u]; i; i = E[i].nex) { int v = E[i].to; if(E[i].val > 0 && dis[v] > dis[u] + E[i].cost) { dis[v] = dis[u] + E[i].cost; pre[v].to = u; pre[v].edge = i; if(!vis[v]) { vis[v] = 1; que.push(v); } } } } if(dis[t] != 0x3f3f3f3f) return true; else return false; } int ans, cos1; void EK() { ans = cos1 = 0; while(spfa()) { int mi = INF; for(int i = t; i != s; i = pre[i].to) { mi = min(mi, E[pre[i].edge].val); } for(int i = t; i != s; i = pre[i].to) { E[pre[i].edge].val -= mi; E[pre[i].edge ^ 1].val += mi; } ans += mi; cos1 += mi * dis[t]; } } int main() { scanf("%d%d%d%d", &n, &m, &s, &t); cnt = 1; for(int i = 1; i <= m; i++) { int a, b, c, d; scanf("%d%d%d%d", &a, &b, &c, &d); addedge(a, b, c, d); addedge(b, a, 0, -d); } EK(); printf("%d %d ", ans, cos1); return 0; }
Dinic多路增广 + 弧优化 + spfa (1744ms)
#include <bits/stdc++.h> using namespace std; const int INF = 1e9; int n, m, s, t, cnt; int maxflow, mincost; struct node { int to, nex, val, cost; }E[100005]; int head[5005]; int cur[5005]; void addedge(int x, int y, int va, int cos) { E[++cnt].to = y; E[cnt].nex = head[x]; head[x] = cnt; E[cnt].val = va; E[cnt].cost = cos; } struct no1 { int to, edge; }pre[5005]; int dis[5005]; int inque[5005]; int vis[5005]; bool spfa() { for(int i = 1; i <= n; i++) inque[i] = 0, dis[i] = 0x3f3f3f3f, cur[i] = head[i], vis[i] = 0; queue<int> que; que.push(s); inque[s] = 1; dis[s] = 0; while(!que.empty()) { int u = que.front(); inque[u] = 0; que.pop(); for(int i = head[u]; i; i = E[i].nex) { int v = E[i].to; if(E[i].val > 0 && dis[v] > dis[u] + E[i].cost) { dis[v] = dis[u] + E[i].cost; pre[v].to = u; pre[v].edge = i; if(!inque[v]) { inque[v] = 1; que.push(v); } } } } if(dis[t] != 0x3f3f3f3f) return true; else return false; } int dfs(int x, int flow) { if(x == t) { vis[x] = 1; maxflow += flow; return flow; } vis[x] = 1; int used = 0; int rflow = 0; for(int i = cur[x]; i; i = E[i].nex) { cur[x] = i; int v = E[i].to; if(E[i].val > 0 && dis[v] == dis[x] + E[i].cost && (!vis[v] || v == t)) { if(rflow = dfs(v, min(flow - used, E[i].val))) { used += rflow; E[i].val -= rflow; E[i ^ 1].val += rflow; mincost += E[i].cost * rflow; if(used == flow) break; } } } return used; } void dinic() { maxflow = mincost = 0; while(spfa()) { vis[t] = 1; while(vis[t]) { memset(vis, 0, sizeof(vis)); dfs(s, INF); } } } int main() { scanf("%d%d%d%d", &n, &m, &s, &t); cnt = 1; for(int i = 1; i <= m; i++) { int a, b, c, d; scanf("%d%d%d%d", &a, &b, &c, &d); addedge(a, b, c, d); addedge(b, a, 0, -d); } dinic(); printf("%d %d ", maxflow, mincost); return 0; }