// Dinic 是EK的优化 (都是FF思想)
//附带EK算法O(V*E2):
1 #include<cstdio> 2 #include<algorithm> 3 #include<queue> 4 #define INF 0x3f3f3f3f 5 using namespace std; 6 7 inline int read() { 8 char c=getchar();int x=0,f=1; 9 while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} 10 while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();} 11 return x*f; 12 } 13 14 const int MAXN = 10000+5; 15 const int MAXE = 100000*2+5; 16 17 int num; 18 int head[MAXN]; 19 struct node { 20 int u, v, flow; 21 int next; 22 } edge[MAXE]; 23 24 inline void add(int x, int y, int w) { 25 edge[num].u = x; 26 edge[num].v = y; 27 edge[num].flow = w; 28 edge[num].next = head[x]; 29 head[x] = num++; 30 } 31 32 int n, m, s, e; 33 int path[MAXN], A[MAXN]; 34 35 int EK() { 36 int ans = 0; 37 while(1) { 38 for(int i = 1; i <= n; ++i) A[i] = 0; 39 queue<int> q; 40 q.push(s); 41 A[s] = INF; 42 while(!q.empty()) { 43 int u = q.front(); 44 q.pop(); 45 for(int i = head[u]; i != -1; i = edge[i].next) { 46 int v = edge[i].v; 47 if(!A[v] && edge[i].flow) { 48 path[v] = i; 49 A[v] = min(A[u], edge[i].flow); 50 q.push(v); 51 } 52 } 53 if(A[e]) break; 54 } 55 if(!A[e]) break; 56 for(int i = e; i != s; i = edge[path[i]].u) { 57 edge[path[i]].flow -= A[e]; 58 edge[path[i]^1].flow += A[e]; 59 } 60 ans += A[e]; 61 } 62 return ans; 63 } 64 65 int main() { 66 n = read(); m = read(); s = read(); e = read(); 67 num = 0; 68 for(int i = 1; i <= n; ++i) head[i] = -1; 69 for(int i = 0; i != m; ++i) { 70 int x = read(), y = read(), w = read(); 71 add(x, y, w); 72 add(y, x, 0); 73 } 74 printf("%d ", EK()); 75 return 0; 76 }
Dinic 参考博客 点我.
Dinic 的三种优化: 当前弧优化、多路增广、炸点 。上面的博客讲的很清楚
代码:
1 /* 2 * @Promlem: 3 * @Time Limit: ms 4 * @Memory Limit: k 5 * @Author: pupil-XJ 6 * @Date: 2019-11-10 19:34:37 7 * @LastEditTime: 2019-11-10 20:56:40 8 */ 9 #include<cstdio> 10 #include<algorithm> 11 #include<queue> 12 #define INF 0x3f3f3f3f 13 using namespace std; 14 15 inline int read() { 16 char c=getchar();int x=0,f=1; 17 while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} 18 while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();} 19 return x*f; 20 } 21 22 const int MAXN = 200+5; 23 const int MAXE = 200*2+5; 24 25 int num; 26 int head[MAXN]; 27 struct node { 28 int v, flow; 29 int next; 30 } edge[MAXN]; 31 32 inline void add(int x, int y, int w) { 33 edge[num].v = y; 34 edge[num].flow = w; 35 edge[num].next = head[x]; 36 head[x] = num++; 37 } 38 39 int n, m, s, e; 40 int cur[MAXN], dis[MAXN]; 41 42 bool bfs() { 43 for(int i = 1; i <= n; ++i) dis[i] = 0; 44 dis[s] = 1; 45 queue<int> q; 46 q.push(s); 47 while(!q.empty()) { 48 int u = q.front(); if(u == e) return true; 49 q.pop(); 50 for(int i = head[u]; i != -1; i = edge[i].next) { 51 int v = edge[i].v; 52 if(!dis[v] && edge[i].flow) { 53 dis[v] = dis[u] + 1; 54 q.push(v); 55 } 56 } 57 } 58 return dis[e] != 0; 59 } 60 61 int dfs(int u, int f) { //当前节点,到目前为止可增加流量。返回可增加流量 62 if(u == e || (!f)) return f; // 到达汇点 || 已无残量 63 int flow = 0; 64 for(int& i = cur[u]; i != -1; i = edge[i].next) {// '&'目的 -> 当前弧优化 65 int v = edge[i].v; 66 if(dis[v] == dis[u] + 1) { 67 int di = dfs(v, min(f, edge[i].flow)); 68 if(di > 0) { 69 flow += di;//这里不急着return,而是记录一下这条链上能增广的流量,再接着找下一条链 70 f -= di;//把从u开始能增广的容量相应减去 71 edge[i].flow -= di; 72 edge[i^1].flow += di; 73 if(!f) break;// 没容量了 74 } 75 } 76 } 77 if(!flow) dis[u] = -1;//这个点甚至没有增广出一点流量,炸掉它 78 return flow; 79 } 80 81 int Dinic() { 82 int ans = 0; 83 while(bfs()) { 84 for(int i = 1; i <= n; ++i) cur[i] = head[i]; 85 ans += dfs(s, INF); 86 } 87 return ans; 88 } 89 90 int main() { 91 n = read(); m = read(); s = read(); e = read(); 92 num = 0; 93 for(int i = 1; i <= n; ++i) head[i] = -1; 94 for(int i = 0; i != m; ++i) { 95 int x = read(), y = read(), w = read(); 96 add(x, y, w); 97 add(y, x, 0); 98 } 99 printf("%d ", Dinic()); 100 return 0; 101 }
// 费用流 定义: 百度百科
// 例题 poj 2516
1 /* 2 * @Promlem: 3 * @Time Limit: ms 4 * @Memory Limit: k 5 * @Author: pupil-XJ 6 * @Date: 2019-11-11 22:37:28 7 * @LastEditTime: 2019-11-12 11:13:39 8 */ 9 #include<cstdio> 10 #include<ctime> 11 #include<algorithm> 12 #include<stack> 13 #include<map> 14 using namespace std; 15 const int INF = 0x3f3f3f3f; 16 typedef pair<int,int> Pair; 17 const int MAXN = 800+5; 18 const int MAXE = 102000+5; 19 20 int num; 21 int head[MAXN]; 22 struct node { 23 int v, flow, dis; 24 int next; 25 } edge[MAXE]; 26 27 inline void add(int x, int y, int w, int d) { 28 edge[num].v = y; 29 edge[num].flow = w; 30 edge[num].dis = d; 31 edge[num].next = head[x]; 32 head[x] = num++; 33 } 34 35 int n, m, k, sum; 36 int S, T; 37 38 int maxflow, mincost; 39 int flow[MAXN], dis[MAXN]; 40 int pre[MAXN], last[MAXN]; 41 bool vis[MAXN]; 42 43 bool spfa() { 44 for(int i = 1; i <= T; ++i) flow[i] = dis[i] = INF, vis[i] = false; 45 dis[S] = 0; 46 vis[S] = true; 47 pre[T] = -1; 48 stack<int> q; 49 q.push(S); 50 while(!q.empty()) { 51 int u = q.top(); 52 q.pop(); 53 vis[u] = false; 54 for(int i = head[u]; i != -1; i = edge[i].next) { 55 int v = edge[i].v; 56 if(edge[i].flow && dis[v] > dis[u] + edge[i].dis) { 57 dis[v] = dis[u] + edge[i].dis; 58 pre[v] = u; 59 last[v] = i; 60 flow[v] = min(flow[u], edge[i].flow); 61 if(!vis[v]) { 62 vis[v] = true; 63 q.push(v); 64 } 65 } 66 } 67 } 68 return pre[T] != -1; 69 } 70 71 bool MCMF() { 72 maxflow = mincost = 0; 73 while(spfa()) { 74 maxflow += flow[T]; 75 mincost += flow[T]*dis[T]; 76 int u = T; 77 while(u != S) { 78 edge[last[u]].flow -= flow[T]; 79 edge[last[u]^1].flow += flow[T]; 80 u = pre[u]; 81 } 82 } 83 return maxflow == sum; 84 } 85 86 int need[155][155], have[155][155], cost[155][155][155]; 87 88 void draw(int k_num) { 89 S = 1; T = 2+m+n; 90 num = sum = 0; 91 for(int i = 1; i <= T; ++i) head[i] = -1; 92 for(int i = 2; i <= 1+m; ++i) { 93 add(S, i, have[i-1][k_num], 0); 94 add(i, S, 0, 0); 95 } 96 for(int i = 2; i <= 1+m; ++i) { 97 for(int j = 2+m; j <= 1+m+n; ++j) { 98 add(i, j, INF, cost[j-1-m][i-1][k_num]); 99 add(j, i, 0, -cost[j-1-m][i-1][k_num]); 100 } 101 } 102 for(int i = 2+m; i <= 1+m+n; ++i) { 103 add(i, T, need[i-1-m][k_num], 0); 104 add(T, i, 0, 0); 105 sum += need[i-1-m][k_num]; 106 } 107 } 108 109 int solve() { 110 int ans = 0; 111 for(int i = 1; i <= k; ++i) { 112 draw(i); 113 if(MCMF()) ans += mincost; 114 else return -1; 115 } 116 return ans; 117 } 118 119 void input() { 120 int x; 121 for(int i = 1; i <= n; ++i) { 122 for(int j = 1; j <= k; ++j) { 123 scanf("%d", &x); 124 need[i][j] = x; 125 } 126 } 127 for(int i = 1; i <= m; ++i) { 128 for(int j = 1; j <= k; ++j) { 129 scanf("%d", &x); 130 have[i][j] = x; 131 } 132 } 133 for(int i = 1; i <= k; ++i) { 134 for(int u = 1; u <= n; ++u) { 135 for(int v = 1; v <= m; ++v) { 136 scanf("%d", &x); 137 cost[u][v][i] = x; 138 } 139 } 140 } 141 } 142 143 int main() { 144 while(1) { 145 scanf("%d%d%d", &n, &m, &k); 146 if(!n) break; 147 input(); 148 printf("%d ", solve()); 149 } 150 return 0; 151 }
SPFA写法--在每次找增广路的时候选择找一条到汇点费用之和最小的链 然后 ans += 当前找到的最短路*每次的增广量
(dijkstra不会。。。)
1 /* 2 * @Promlem: 3 * @Time Limit: ms 4 * @Memory Limit: k 5 * @Author: pupil-XJ 6 * @Date: 2019-11-11 19:02:37 7 * @LastEditTime: 2019-11-11 19:20:27 8 */ 9 10 #include<cstdio> 11 #include<algorithm> 12 #include<queue> 13 #define INF 0x3f3f3f3f 14 using namespace std; 15 16 inline int read() { 17 char c=getchar();int x=0,f=1; 18 while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} 19 while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();} 20 return x*f; 21 } 22 23 const int MAXN = 200+5; 24 const int MAXE = 200*2+5; 25 26 int num; 27 int head[MAXN]; 28 struct node { 29 int v, flow, dis; 30 int next; 31 } edge[MAXN]; 32 33 inline void add(int x, int y, int w, int dis) { 34 edge[num].v = y; 35 edge[num].flow = w; 36 edge[num].dis = dis; 37 edge[num].next = head[x]; 38 head[x] = num++; 39 } 40 41 int n, m, s, e; 42 int maxflow, mincost; 43 int flow[MAXN], dis[MAXN]; 44 int pre[MAXN], last[MAXN]; 45 bool vis[MAXN]; 46 47 bool spfa() { 48 for(int i = 1; i <= n; ++i) flow[i] = dis[i] = INF, vis[i] = false; 49 vis[s] = true; 50 dis[s] = 0; pre[e] = -1; 51 queue<int> q; 52 q.push(s); 53 while(!q.empty()) { 54 int u = q.front(); 55 q.pop(); 56 vis[u] = false; 57 for(int i = head[u]; i != -1; i = edge[i].next) { 58 int v = edge[i].v; 59 if(edge[i].flow && dis[v] > dis[u] + edge[i].dis) { 60 dis[v] = dis[u] + edge[i].dis; 61 pre[v] = u; 62 last[v] = i; 63 flow[v] = min(flow[u], edge[i].flow); 64 if(!vis[v]) { 65 vis[v] = true; 66 q.push(v); 67 } 68 } 69 } 70 } 71 return pre[e] != -1; 72 } 73 74 void MCMF() { 75 maxflow = mincost = 0; 76 while(spfa()) { 77 int u = e; 78 maxflow += flow[u]; 79 mincost += flow[u]*dis[u]; 80 while(u != s) { 81 edge[last[u]].flow -= flow[e]; 82 edge[last[u]^1].flow += flow[e]; 83 u = pre[u]; 84 } 85 } 86 } 87 88 int main() { 89 n = read(); m = read(); s = read(); e = read(); 90 num = 0; 91 for(int i = 1; i <= n; ++i) head[i] = -1; 92 for(int i = 0; i != m; ++i) { 93 int x = read(), y = read(), w = read(), f = read(); 94 add(x, y, w, f); 95 add(y, x, 0,-f); 96 } 97 MCMF(); 98 printf("%d %d ", maxflow, mincost); 99 return 0; 100 }