Dinic算法学习可参考2007年的一篇国家队论文《浅谈基于分层思想的网络流算法》或者参考《算法设计技巧和分析》(沙特),我觉得这本书讲的更清楚一下,网上英文版有电子版 #include <stdio.h> #include <string.h> #include <algorithm> using namespace std; const int MAXN = 1005; const int MAXM = 210000; const int INF = 1000000000; struct Edge { int st, ed; int next; int flow; }edge[MAXM]; int head[MAXN]; int value[MAXN]; int N, M, F, E; int src, dest; int seq[MAXM], sl; int ans = 0; void add_edge(int &u, int &v, int &w) { edge[E].flow = w; edge[E].st = u; edge[E].ed = v; edge[E].next = head[u]; head[u] = E++; edge[E].flow = 0; edge[E].st = v; edge[E].ed = u; edge[E].next = head[v]; head[v] = E++; } void Init() { int i, u, v, w; E = 0; ans = 0; memset(head, -1, sizeof(head)); //memset(value, -1, sizeof(value)); scanf("%d %d %d", &N, &M, &F); for(i = 0; i < M; i++) { scanf("%d %d %d", &u, &v, &w); add_edge(u, v, w); } N++; for(i = 0; i < F; i++) { scanf("%d %d", &u, &v); value[u] = v; ans += v; add_edge(u, N, v); } src = 1; dest = N; } // int d[MAXN]; bool dinic_bfs() { int i, j; memset(d, -1, sizeof(d)); int que[MAXN], rear = 1; que[0] = src; d[src] = 0; for(i = 0; i < rear; i++) for(j = head[que[i]]; j != -1; j = edge[j].next) if(d[edge[j].ed] == -1 && edge[j].flow > 0) { d[edge[j].ed] = d[que[i]]+1; que[rear++] = edge[j].ed; } return d[dest] >= 0; } int dinic_dfs() { int stk[MAXN], top = 0; int ret = 0, cur, ptr, pre[MAXN], minf, i; bool del[MAXN]; memset(del, false, sizeof(del)); stk[top++] = src; pre[src] = src; cur = src; while(top) { while(cur != dest && top) { for(i = head[cur]; i != -1; i = edge[i].next) { if(d[edge[i].ed] == d[cur]+1 && edge[i].flow > 0 && !del[edge[i].ed]) { stk[top++] = edge[i].ed; cur = edge[i].ed; pre[edge[i].ed] = i; break; } } if(i == -1) { del[cur] = 1; top--; if(top) cur = stk[top-1]; } } //update the flow if(cur == dest) { minf = INF; while(cur != src) { cur = pre[cur]; if(edge[cur].flow < minf) minf = edge[cur].flow; cur = edge[cur].st; } cur = dest; while(cur != src) { cur = pre[cur]; edge[cur].flow -= minf; edge[cur^1].flow += minf; if(edge[cur].flow == 0) ptr = edge[cur].st; cur = edge[cur].st; } while(top > 0&& stk[top-1] != ptr) top--; if(top) cur = stk[top-1]; ret += minf; } } return ret; } int Dinic() { int ret = 0, t; while(dinic_bfs()) { t = dinic_dfs(); if(t) ret += t; else break; } return ret; } bool used[MAXN]; void floodfill(int t) { int i ; used[t] = true; //printf("t = %d/n", t); for(i = head[t]; i != -1; i = edge[i].next) { if(!used[edge[i].ed] && edge[i].flow > 0) { floodfill(edge[i].ed); } } } void MinCut() { int i, j; int ret = 0; memset(used, 0, sizeof(used)); floodfill(src); sl = 0; for(i = 1; i < N; i++) for(j = head[i]; j != -1; j = edge[j].next) { if(used[i] && !used[edge[j].ed]) { ans -= edge[j^1].flow; if(j/2+1 <= M) seq[sl++] = j/2+1; } } sort(seq, seq+sl); //while(seq[sl-1] > M) sl--; printf("%d/n", ans); printf("%d", sl); for(i = 0; i < sl; i++) { printf(" %d", seq[i]); } puts(""); } int main() { int T, CAS = 1; scanf("%d", &T); while(T--) { Init(); Dinic(); printf("Case %d: ", CAS++); MinCut(); } return 0; } /* MPLA,最短路径增值算法 O(M*M*N) 1、初始化流量,计算剩余图 2、根绝剩余图计算层次图。若汇点不再层次图内,则算法结束 3、在层次图内不断bfs增广,直到没有增广路为止 4、转步骤2 最多建立n次层次图,每次复杂度O(m),每次最多增广m次,所以总的复杂度 为O(n*m*m) */ bool dinic_bfs() { int i, j; memset(d, -1, sizeof(d)); int que[MAXN], rear = 1; que[0] = src; d[src] = 0; for(i = 0; i < rear; i++) for(j = head[que[i]]; j != -1; j = edge[j].next) if(d[edge[j].ed] == -1 && edge[j].flow > 0) { d[edge[j].ed] = d[que[i]]+1; que[rear++] = edge[j].ed; } return d[dest] >= 0; } //增广DFS int dinic_dfs(int t, int cp) { int i, tmp; if(t == dest) return cp; for(i = head[t]; i != -1; i = edge[i].next) { if(edge[i].flow > 0 && d[edge[i].ed] == d[t]+1 && (tmp = dinic_dfs(edge[i].ed, (cp > edge[i].flow) ? edge[i].flow : cp))) { edge[i].flow -= tmp; edge[i^1].flow += tmp; return tmp; } } return 0; } int Dinic() { int ans = 0, flow; while(dinic_bfs()) { while((flow = dinic_dfs(src))) ans += flow; } return ans; }