传送门:
以前没接触过最大流问题,刚开始以为是用kruscal算法求最小生成树呢,并且题上也是显示最小树的专题:
反正还行吧,捣鼓了两天,总算稍微理解了一下,等会回来整理一下知识点。
1 #include <iostream> 2 #include <queue> 3 #include <algorithm> 4 #include <cstring> 5 #include <cstdio> 6 using namespace std; 7 const int N=201; 8 int maxData=1<<30; 9 int capacity[N][N];//记录残留网络的容量: 10 int flow[N]; //标记从源点到当前节点实际还剩多少流量可用 11 int pre[N]; //标记在这条路径上当前节点的前驱,同时标记该节点是否在队列中 12 int n,m; 13 queue<int> q; 14 int bfs(int src,int des) //找增广路径 15 { 16 int i,j; 17 while(!q.empty())//清空队列 18 q.pop(); 19 for(i=1;i<m+1;i++) 20 pre[i]=-1; 21 pre[src]=0; 22 flow[src]=maxData; 23 q.push(src); 24 while(!q.empty()) 25 { 26 int index=q.front(); 27 q.pop(); 28 if(index==des) //找到增广路径 29 break; 30 for(i=1;i<=m;i++) 31 if(/*i!=src&&*/ capacity[index][i]>0&&pre[i]==-1) 32 { 33 pre[i]=index;//记录前驱 34 flow[i]=min(capacity[index][i],flow[index]);//关键:迭代的找到增量 35 q.push(i); 36 } 37 } 38 if(pre[des]==-1)//残留图中不再存在增广路径 39 return -1; 40 else 41 return flow[des]; 42 } 43 44 int maxFlow(int src,int des) //求最大流 45 { 46 int increasement=0; 47 int sumflow=0; 48 while((increasement=bfs(src,des))!=-1) 49 { 50 int k=des;//利用前驱寻找路径 51 while(k!=src) 52 { 53 int last =pre[k]; 54 capacity[last][k]-=increasement;//改变正向的容量 55 capacity[k][last]+=increasement;//改变反向的容量 56 k=last; 57 } 58 sumflow+=increasement; 59 } 60 return sumflow; 61 } 62 63 int main() 64 { 65 int i,j; 66 int start,end,ci; 67 while(~scanf("%d%d",&n,&m)) 68 { 69 memset(capacity,0,sizeof(capacity)); 70 memset(flow,0,sizeof(flow)); 71 for(i=0;i<n;i++) 72 { 73 scanf("%d%d%d",&start,&end,&ci); 74 capacity[start][end]+=ci;//注意可能出现多条同一起点终点的情况 75 } 76 printf("%d\n",maxFlow(1,m)); 77 } 78 return 0; 79 } 80
时间: 2024-10-13 03:56:05