P3376 【模板】网络最大流dinic算法
题目描述
如题,给出一个网络图,以及其源点和汇点,求出其网络最大流。
输入输出格式
输入格式:
第一行包含四个正整数N、M、S、T,分别表示点的个数、有向边的个数、源点序号、汇点序号。
接下来M行每行包含三个正整数ui、vi、wi,表示第i条有向边从ui出发,到达vi,边权为wi(即该边最大流量为wi)
输出格式:
一行,包含一个正整数,即为该网络的最大流。
输入输出样例
输入样例#1:
4 5 4 3 4 2 30 4 3 20 2 3 20 2 1 30 1 3 40
输出样例#1:
50
说明
时空限制:1000ms,128M
数据规模:
对于30%的数据:N<=10,M<=25
对于70%的数据:N<=200,M<=1000
对于100%的数据:N<=10000,M<=100000
样例说明:
题目中存在3条路径:
4-->2-->3,该路线可通过20的流量
4-->3,可通过20的流量
4-->2-->1-->3,可通过10的流量(边4-->2之前已经耗费了20的流量)
故流量总计20+20+10=50。输出50。
分析
dinic算法,需要注意许多点:
- 反向边初始值容量为0,
- 异或符号,x^1,x为偶数+1,奇数-1;所以第一条边为偶数,所以我的第一条边是2,他的反向边是3;
- 数据范围,这个就不多说了,反向建边,数组大小要乘2
code
1 #include<cstdio> 2 #include<algorithm> 3 4 using namespace std; 5 6 const int N = 20100; 7 const int INF = 1e9; 8 9 struct Edge{ 10 int to,c,nxt; 11 }e[500100]; 12 13 int q[5000100],head[N],dis[N],cur[N]; 14 int S,T,n,m,L,R,tot = 1; 15 16 inline char nc() { 17 static char buf[100000],*p1 = buf,*p2 = buf; 18 return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2) ? EOF : *p1++; 19 } 20 inline int read() { 21 int x = 0,f = 1;char ch = nc(); 22 for (; ch<'0'||ch>'9'; ch = nc()) if (ch=='-') f = -1; 23 for (; ch>='0'&&ch<='9'; ch = nc()) x = x * 10 + ch - '0'; 24 return x * f; 25 } 26 inline void add_edge(int u,int v,int w) { 27 e[++tot].to = v,e[tot].c = w,e[tot].nxt = head[u],head[u] = tot; 28 e[++tot].to = u,e[tot].c = 0,e[tot].nxt = head[v],head[v] = tot; 29 } 30 inline bool bfs() { 31 for (int i=1; i<=n; ++i) { 32 cur[i] = head[i];dis[i] = -1; 33 } 34 L = 1;R = 0; 35 q[++R] = S; 36 dis[S] = 0; 37 while (L <= R) { 38 int u = q[L++]; 39 for (int i=head[u]; i; i=e[i].nxt) { 40 int v = e[i].to,c = e[i].c; 41 if (dis[v]==-1 && c>0) { 42 q[++R] = v; 43 dis[v] = dis[u] + 1; 44 if (v==T) return true; 45 } 46 } 47 } 48 return false; 49 } 50 int dfs(int u,int flow) { 51 if (u==T) return flow; 52 int used = 0; 53 for (int & i=cur[u]; i; i=e[i].nxt) { 54 int v = e[i].to,c = e[i].c; 55 if (dis[v]==dis[u]+1 && c>0) { 56 int tmp = dfs(v,min(c,flow-used)); 57 if (tmp > 0) { 58 e[i].c -= tmp;e[i^1].c += tmp; 59 used += tmp; 60 if (used==flow) break; 61 } 62 } 63 } 64 if (used != flow) dis[u] = -1; 65 return used; 66 } 67 inline int dinic() { 68 int ans = 0; 69 while (bfs()) 70 ans += dfs(S,INF); 71 return ans; 72 } 73 int main() { 74 n = read(),m = read(),S = read(),T = read(); 75 for (int a,b,c,i=1; i<=m; ++i) { 76 a = read(),b = read(),c = read(); 77 add_edge(a,b,c); 78 } 79 printf("%d",dinic()); 80 return 0; 81 }
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<queue> 5 using namespace std; 6 7 const int MAXN = 100100; 8 const int INF = 1e9; 9 10 struct Edge{ 11 int to,c,nxt; 12 Edge(){} 13 Edge(int tt,int cc,int nn) {to = tt,c = cc,nxt = nn;} 14 }e[1000100]; 15 queue<int>q; 16 17 int head[MAXN],dis[MAXN]; 18 int s,t,n,m,tot = 1; 19 20 int read() 21 { 22 int x = 0, f = 1;char ch = getchar(); 23 while (ch<'0'||ch>'9') {if (ch=='-') f = -1; ch = getchar();} 24 while (ch>='0'&&ch<='9') {x = x*10+ch-'0'; ch = getchar();} 25 return x*f; 26 } 27 bool bfs() 28 { 29 q.push(s); 30 memset(dis,-1,sizeof(dis)); 31 dis[s] = 0; 32 while (!q.empty()) 33 { 34 int u = q.front(); 35 q.pop(); 36 for (int i=head[u]; i; i=e[i].nxt) 37 { 38 int v = e[i].to; 39 if (dis[v]==-1&&e[i].c>0) 40 { 41 dis[v] = dis[u]+1; 42 q.push(v); 43 } 44 } 45 } 46 if (dis[t]!=-1) return true; 47 return false; 48 } 49 int dfs(int u,int low) 50 { 51 if (u==t) return low; 52 int w,used = 0; 53 for (int i=head[u]; i; i=e[i].nxt) 54 { 55 int v = e[i].to; 56 if (dis[v]==dis[u]+1&&e[i].c>0) 57 { 58 w = dfs(v,min(low-used,e[i].c)); 59 e[i].c -= w; 60 e[i^1].c += w; 61 used += w; 62 if (used==low) return low; 63 } 64 } 65 if (!used) dis[u] = -1; 66 return used; 67 } 68 int dinic() 69 { 70 int ans = 0,t; 71 while (bfs()) 72 ans += dfs(s,INF); 73 return ans; 74 } 75 int main() 76 { 77 n = read();m = read();s = read();t = read(); 78 for (int u,v,w,i=1; i<=m; ++i) 79 { 80 u = read();v = read();w = read(); 81 e[++tot] = Edge(v,w,head[u]); 82 head[u] = tot; 83 e[++tot] = Edge(u,0,head[v]); 84 head[v] = tot; 85 } 86 printf("%d",dinic()); 87 return 0; 88 }