Drainage Ditches(最大流入门)
EK+邻接矩阵:
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 #define rep(i,first,last) for(int i=first;i<=last;i++) 5 #define dep(i,first,last) for(int i=first;i>=last;i--) 6 const int maxn=205; 7 const int inf=0x3f3f3f3f; 8 int graph[maxn][maxn]; 9 int pre[maxn];//记录前驱节点 10 int vis[maxn]; 11 int n,m,a,b,flow; 12 13 int BFS(int st,int ed){ 14 memset(vis,0,sizeof(vis)); 15 queue<int>que; 16 while(!que.empty()) que.pop(); 17 que.push(st); 18 vis[st]=1; 19 int curr,flow=inf; 20 pre[st]=pre[ed]=-1; 21 while(!que.empty()){ 22 curr=que.front(); 23 que.pop(); 24 if( curr==ed ) break; 25 rep(nxt,1,n){ 26 if(!vis[nxt]&&graph[curr][nxt]!=0){ 27 vis[nxt]=1; 28 if( flow>graph[curr][nxt]) flow=graph[curr][nxt]; 29 pre[nxt]=curr; 30 que.push(nxt); 31 } 32 } 33 } 34 if(pre[ed]==-1) return -1;//没有找到增广路 35 return flow; 36 } 37 38 int EK(int st,int ed){ 39 int stream; 40 int sum=0; 41 while((stream=BFS(st,ed))!=-1 ){ //找到了增广路 42 int u=ed; 43 while( pre[u]!=-1 ){ 44 graph[pre[u]][u]-=stream;//改变正向边的容量 45 graph[u][pre[u]]+=stream;//改变反向边的容量 46 u=pre[u]; 47 } 48 sum += stream; 49 } 50 return sum; 51 } 52 int main() 53 { 54 while(~scanf("%d%d",&m,&n)){ 55 memset(graph,0,sizeof(graph)); 56 memset(vis,0,sizeof(vis)); 57 while( m-- ){ 58 scanf("%d%d%d",&a,&b,&flow); 59 graph[a][b]+=flow;//此处注意可能出现多条同一起点终点的情况 60 } 61 printf("%d\n",EK(1,n)); 62 } 63 return 0; 64 }
EK+前向星:
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int maxn=210; 5 const int inf=0x3f3f3f3f; 6 #define rep(i,first,last) for(int i=first;i<=last;i++) 7 #define dep(i,first,last) for(int i=first;i>=last;i--) 8 int head[maxn<<1],cnt; 9 struct node{int to,nxt,val;}e[maxn<<1]; 10 void addedge(int u,int v,int val){ 11 e[cnt].to=v; 12 e[cnt].val=val; 13 e[cnt].nxt=head[u]; 14 head[u]=cnt++; 15 } 16 int vis[maxn],pre[maxn]; 17 int BFS(int st,int ed){ 18 memset(vis,0,sizeof(vis)); 19 vis[st]=1; 20 queue<int>que; 21 while(!que.empty()) que.pop(); 22 que.push(st); 23 int u,v,flow=inf; 24 pre[st]=pre[ed]=-1; 25 while(!que.empty()){ 26 u=que.front(); 27 que.pop(); 28 if( u==ed ) break; 29 for(int i=head[u];~i;i=e[i].nxt ){ 30 v=e[i].to; 31 if(!vis[v]&&e[i].val>0){ 32 vis[v]=1; 33 flow=min(flow,e[i].val); 34 pre[v]=i;//注意是i,不是u 35 que.push(v); 36 } 37 } 38 } 39 if( pre[ed]==-1 ) return -1; 40 return flow; 41 } 42 int EK(int st,int ed){ 43 int stream,flow=0; 44 while((stream=BFS(st,ed))!=-1 ){ 45 //pre通过节点存边的坐标,通过边的反向边的to获取上一个节点 46 for(int i=pre[ed];~i;i=pre[e[i^1].to]){ 47 e[i].val-=stream; 48 e[i^1].val+=stream; 49 } 50 flow+=stream; 51 } 52 return flow; 53 } 54 int main() 55 { 56 int a,b,n,m,flow; 57 while(~scanf("%d%d",&m,&n)){ 58 memset(head,-1,sizeof(head)); 59 cnt=0; 60 while( m-- ){ 61 scanf("%d%d%d",&a,&b,&flow); 62 addedge(a,b,flow); 63 addedge(b,a,0); 64 } 65 printf("%d\n",EK(1,n)); 66 } 67 return 0; 68 }
FF+邻接矩阵:
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int maxn=210; 5 const int inf=0x3f3f3f3f; 6 #define rep(i,first,last) for(int i=first;i<=last;i++) 7 #define dep(i,first,last) for(int i=first;i>=last;i--) 8 int graph[maxn][maxn]; 9 int vis[maxn]; 10 int n,m; 11 int dfs(int st,int ed,int f){//在没有走到汇点前我们不知道流量是多少,所以f是动态更新的 12 vis[st]=1; 13 if(st==ed) return f;//走到汇点返回本次增广的流量 14 rep(i,1,n){ 15 if( graph[st][i]>0 && vis[i]==0 ){ 16 int d=dfs(i,ed,min(graph[st][i],f)); 17 if( d>0 ){//顺着流过去,要受一路上最小容量的限制 18 graph[st][i]-=d; 19 graph[i][st]+=d; 20 return d; 21 } 22 } 23 } 24 return 0;//无法到汇点 25 } 26 int FF(int st,int ed){ 27 int flow=0,curr; 28 while(1){ 29 memset(vis,0,sizeof(vis)); 30 curr=dfs(st,ed,inf); 31 if( curr==0 ) return flow; 32 flow+=curr; 33 } 34 } 35 int main() 36 { 37 int a,b,val; 38 while(~scanf("%d%d",&m,&n)){ 39 memset(graph,0,sizeof(graph)); 40 while(m--){ 41 scanf("%d%d%d",&a,&b,&val); 42 graph[a][b]+=val; 43 } 44 printf("%d\n",FF(1,n)); 45 } 46 return 0; 47 }
FF+邻接表:
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int maxn=210; 5 const int inf=0x3f3f3f3f; 6 #define rep(i,first,last) for(int i=first;i<=last;i++) 7 #define dep(i,first,last) for(int i=first;i>=last;i--) 8 struct node{ 9 int to; 10 int flow; 11 int rev;//反向边在数组中的位置 12 node(){} 13 node(int to,int flow,int rev):to(to),flow(flow),rev(rev){} 14 }; 15 vector<node>graph[maxn]; 16 int vis[maxn]; 17 int n,m; 18 void addedge(int from,int to,int val){ 19 graph[from].push_back(node(to,val,graph[to].size())); 20 graph[to].push_back(node(from,0,graph[from].size()-1)); 21 } 22 int dfs(int st,int ed,int f){ 23 vis[st]=1; 24 if(st==ed)return f; 25 rep(i,0,graph[st].size()-1){ 26 node &temp=graph[st][i];//注意必须用引用 27 if(!vis[temp.to] && temp.flow>0 ){ 28 int d=dfs(temp.to,ed,min(f,temp.flow)); 29 if( d>0 ){ 30 temp.flow-=d; 31 graph[temp.to][temp.rev].flow+=d; 32 return d; 33 } 34 } 35 } 36 return 0; 37 } 38 int FF(int st,int ed){ 39 int flow=0,curr; 40 while(1){ 41 memset(vis,0,sizeof(vis)); 42 curr=dfs(st,ed,inf); 43 if( curr==0 ) return flow; 44 flow+=curr; 45 } 46 } 47 int main() 48 { 49 int a,b,val; 50 while(~scanf("%d%d",&m,&n)){ 51 rep(i,1,n) graph[i].clear(); 52 while( m-- ){ 53 scanf("%d%d%d",&a,&b,&val); 54 addedge(a,b,val); 55 } 56 printf("%d\n",FF(1,n)); 57 } 58 return 0; 59 }
FF+前向星:
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int maxn=210; 5 const int inf=0x3f3f3f3f; 6 #define rep(i,first,last) for(int i=first;i<=last;i++) 7 #define dep(i,first,last) for(int i=first;i>=last;i--) 8 struct node{int to,nxt,c;}e[maxn<<1]; 9 int head[maxn<<1],cnt,vis[maxn]; 10 void addedge(int u,int v,int val){ 11 e[cnt].to=v; 12 e[cnt].c=val; 13 e[cnt].nxt=head[u]; 14 head[u]=cnt++; 15 } 16 int dfs(int st,int ed,int f){ 17 vis[st]=1; 18 if(st==ed) return f; 19 for(int i=head[st];~i;i=e[i].nxt){ 20 int v=e[i].to,val=e[i].c; 21 if( !vis[v]&&val>0 ){ 22 int d=dfs(v,ed,min(val,f)); 23 if( d>0 ){ 24 e[i].c-=d; 25 e[i^1].c+=d; 26 return d; 27 } 28 } 29 } 30 return 0; 31 } 32 int FF(int st,int ed){ 33 int flow=0,d; 34 while(1){ 35 memset(vis,0,sizeof(vis)); 36 d=dfs(st,ed,inf); 37 if(d==0) return flow; 38 flow+=d; 39 } 40 } 41 int main() 42 { 43 int n,m,a,b,val; 44 while(~scanf("%d%d",&m,&n)){ 45 memset(head,-1,sizeof(head)); 46 cnt=0; 47 while( m-- ){ 48 scanf("%d%d%d",&a,&b,&val); 49 addedge(a,b,val); 50 addedge(b,a,0); 51 } 52 printf("%d\n",FF(1,n)); 53 } 54 return 0; 55 }
Dinic+邻接矩阵:
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int maxn=210; 5 const int inf=0x3f3f3f3f; 6 #define rep(i,first,last) for(int i=first;i<=last;i++) 7 #define dep(i,first,last) for(int i=first;i>=last;i--) 8 int graph[maxn][maxn]; 9 int step[maxn];//相当于将图分层了 10 int n,m; 11 bool bfs(int st,int ed){//bool 函数是一个小优化,判断是否能搜到汇点,如果连汇点都搜不到还dfs干什么 12 memset(step,-1,sizeof(step)); 13 queue<int>que; 14 while(!que.empty()) que.pop(); 15 step[st]=0; 16 que.push(st); 17 while(!que.empty()){ 18 int curr=que.front(); 19 que.pop(); 20 rep(i,1,n){ 21 if(graph[curr][i]>0 && step[i]==-1 ){ 22 step[i]=step[curr]+1; 23 if( i==ed ) return true; 24 que.push(i); 25 } 26 } 27 } 28 return step[ed]!=-1; 29 } 30 int dfs(int st,int ed,int f){ 31 if(st==ed||f==0) return f; 32 int flow=0,d; 33 rep(i,1,n){ 34 if((step[i]==step[st]+1)&&graph[st][i]>0&&(d=dfs(i,ed,min(graph[st][i],f)))){//step[i]==step[st]+1;控制仅允许流向下一层 35 graph[st][i]-=d; 36 graph[i][st]+=d; 37 flow+=d;//累加当前节点的某条路径的合适流量 38 f-=d;//当前节点的容量减去某条路径的合适流量 39 if(f==0) break;//如果当前节点的容量用完,说明无法再通过任何流量 40 } 41 } 42 if( flow==0 ) step[st]=inf;//如果当前节点无任何流量通过,取消标记 43 return flow; 44 } 45 int Dinic(int st,int ed){ 46 int flow=0; 47 while(bfs(st,ed)){ 48 flow+=dfs(st,ed,inf); 49 } 50 return flow; 51 } 52 int main() 53 { 54 int a,b,flow; 55 while(~scanf("%d%d",&m,&n)){ 56 memset(graph,0,sizeof(graph)); 57 while(m--){ 58 scanf("%d%d%d",&a,&b,&flow); 59 graph[a][b]+=flow; 60 } 61 printf("%d\n",Dinic(1,n)); 62 } 63 return 0; 64 }
Dinic+邻接表:
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int maxn=210; 5 const int inf=0x3f3f3f3f; 6 #define rep(i,first,last) for(int i=first;i<=last;i++) 7 #define dep(i,first,last) for(int i=first;i>=last;i--) 8 int step[maxn]; 9 struct node{ 10 int to; 11 int flow; 12 int rev;//记录反向边的index 13 node(){} 14 node(int to,int flow,int rev):to(to),flow(flow),rev(rev){} 15 }; 16 vector<node>graph[maxn]; 17 int n,m; 18 void addedge(int from,int to,int flow){ 19 graph[from].push_back(node(to,flow,graph[to].size())); 20 graph[to].push_back(node(from,0,graph[from].size()-1)); 21 } 22 bool bfs(int st,int ed){ 23 memset(step,-1,sizeof(step)); 24 queue<int>que; 25 que.push(st); 26 step[st]=0; 27 while(!que.empty()){ 28 int curr=que.front(); 29 que.pop(); 30 rep(i,0,graph[curr].size()-1){ 31 node &temp=graph[curr][i]; 32 if(step[temp.to]==-1 && temp.flow>0 ){ 33 step[temp.to]=step[curr]+1; 34 if( temp.to==ed ) return true; 35 que.push(temp.to); 36 } 37 } 38 } 39 return step[ed]!=-1; 40 } 41 int dfs(int st,int ed,int f){ 42 if( st==ed || f==0 ) return f; 43 int flow=0; 44 rep(i,0,graph[st].size()-1){ 45 node &temp=graph[st][i]; 46 if( temp.flow>0 && step[temp.to]==step[st]+1){ 47 int d=dfs(temp.to,ed,min(f,temp.flow)); 48 if(d>0){ 49 temp.flow-=d; 50 graph[temp.to][temp.rev].flow+=d; 51 flow+=d; 52 f-=d; 53 if(f==0) break; 54 } 55 } 56 } 57 if( flow==0 ) step[st]=inf; 58 return flow; 59 } 60 int Dinic(int st,int ed){ 61 int flow=0; 62 while(bfs(st,ed)){ 63 flow+=dfs(st,ed,inf); 64 } 65 return flow; 66 } 67 int main() 68 { 69 int a,b,flow; 70 while(~scanf("%d%d",&m,&n)){ 71 memset(graph,0,sizeof(graph)); 72 while( m-- ){ 73 scanf("%d%d%d",&a,&b,&flow); 74 addedge(a,b,flow); 75 } 76 printf("%d\n",Dinic(1,n)); 77 } 78 return 0; 79 }
Dinic+前向星:
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int maxn=210; 5 const int inf=0x3f3f3f3f; 6 #define rep(i,first,last) for(int i=first;i<=last;i++) 7 #define dep(i,first,last) for(int i=first;i>=last;i--) 8 int head[maxn<<1],cnt,step[maxn]; 9 struct node{int to,nxt,c;}e[maxn<<1]; 10 void addedge(int u,int v,int val){ 11 e[cnt].to=v; 12 e[cnt].c=val; 13 e[cnt].nxt=head[u]; 14 head[u]=cnt++; 15 } 16 bool bfs(int st,int ed){ 17 memset(step,-1,sizeof(step)); 18 queue<int>que; 19 while(!que.empty())que.pop(); 20 que.push(st); 21 step[st]=0; 22 int u; 23 while(!que.empty()){ 24 u=que.front(); 25 que.pop(); 26 for(int i=head[u];~i;i=e[i].nxt){ 27 int v=e[i].to; 28 if( step[v]==-1 && e[i].c>0 ){ 29 step[v]=step[u]+1; 30 que.push(v); 31 if( v==ed ) return true; 32 } 33 } 34 } 35 return step[ed]!=-1; 36 } 37 38 int dfs(int st,int ed,int flow){ 39 if(st==ed||flow==0) return flow; 40 int curr=0; 41 for(int i=head[st];~i;i=e[i].nxt){ 42 int v=e[i].to; 43 int val=e[i].c; 44 if( step[st]+1==step[v] && val>0 ){ 45 int d=dfs(v,ed,min(val,flow)); 46 if(d>0){ 47 e[i].c-=d; 48 e[i^1].c+=d;//添反向边的时候是相邻的,i^1取相邻数; 49 curr+=d;//累加当前节点的某条路径的合适流量 50 flow-=d;//当前节点的容量减去某条路径的合适流量 51 if(flow==0) break;//如果当前节点的容量用完,说明无法再通过任何流量 52 } 53 } 54 } 55 if( curr==0 ) step[st]=inf;//如果当前节点无任何流量通过,取消标记 56 return curr; 57 } 58 59 int Dinic(int st,int ed){ 60 int flow=0; 61 while(bfs(st,ed)){ 62 flow+=dfs(st,ed,inf); 63 } 64 return flow; 65 } 66 int main() 67 { 68 int n,m,a,b,val; 69 while(~scanf("%d%d",&m,&n)){ 70 memset(head,-1,sizeof(head)); 71 cnt=0; 72 while(m--){ 73 scanf("%d%d%d",&a,&b,&val); 74 addedge(a,b,val); 75 addedge(b,a,0); 76 } 77 printf("%d\n",Dinic(1,n)); 78 } 79 return 0; 80 }
Dinic+前向星+优化:
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int maxn=210; 5 const int inf=0x3f3f3f3f; 6 #define rep(i,first,last) for(int i=first;i<=last;i++) 7 #define dep(i,first,last) for(int i=first;i>=last;i--) 8 int head[maxn<<1],cnt,step[maxn],cur[maxn]; 9 struct node{int to,nxt,c;}e[maxn<<1]; 10 void addedge(int u,int v,int val){ 11 e[cnt].to=v; 12 e[cnt].c=val; 13 e[cnt].nxt=head[u]; 14 head[u]=cnt++; 15 } 16 bool bfs(int st,int ed){ 17 memset(step,-1,sizeof(step)); 18 queue<int>que; 19 while(!que.empty())que.pop(); 20 que.push(st); 21 step[st]=0; 22 int u; 23 while(!que.empty()){ 24 u=que.front(); 25 que.pop(); 26 for(int i=head[u];~i;i=e[i].nxt){ 27 int v=e[i].to; 28 if( step[v]==-1 && e[i].c>0 ){ 29 step[v]=step[u]+1; 30 que.push(v); 31 if( v==ed ) return true; 32 } 33 } 34 } 35 return step[ed]!=-1; 36 } 37 38 int dfs(int st,int ed,int flow){ 39 if(st==ed||flow==0) return flow; 40 int curr=0; 41 for(int &i=cur[st];~i;i=e[i].nxt){ 42 int v=e[i].to; 43 int val=e[i].c; 44 if( step[st]+1==step[v] && val>0 ){ 45 int d=dfs(v,ed,min(val,flow)); 46 if(d>0){ 47 e[i].c-=d; 48 e[i^1].c+=d; 49 curr+=d; 50 flow-=d; 51 if(flow==0) break; 52 } 53 } 54 } 55 if( curr==0 ) step[st]=inf; 56 return curr; 57 } 58 59 int Dinic(int st,int ed){ 60 int flow=0; 61 while(bfs(st,ed)){ 62 rep(i,0,maxn-2) cur[i]=head[i]; 63 flow+=dfs(st,ed,inf); 64 } 65 return flow; 66 } 67 int main() 68 { 69 int n,m,a,b,val; 70 while(~scanf("%d%d",&m,&n)){ 71 memset(head,-1,sizeof(head)); 72 cnt=0; 73 while(m--){ 74 scanf("%d%d%d",&a,&b,&val); 75 addedge(a,b,val); 76 addedge(b,a,0); 77 } 78 printf("%d\n",Dinic(1,n)); 79 } 80 return 0; 81 }