网络流之最大流算法模板EK

来源:互联网 发布:网络板块股票有哪些 编辑:程序博客网 时间:2024/05/10 10:06
#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
int maxdata=0x7fffffff;
int capacity[200][200],c[1000][1000];//c[i][j]保存初值,因为每次计算都会改变capacity[i][j]的值,capacity[i][j]表示残留网络的容量
int flow[200];//标记从源点到当前点实际还有多少容量可用
int pre[200];//标记在这条路径上当前节点的前驱,同时标记该节点是否在队列中
int x[1000],y[10000],len[10000];//x,y,len存储每条边的信息
int n,m,p; //n 表示边数,m表示节点数,p表示操作数
queue<int> myqueue;
int bfs(int src,int des)
{
  int i,j;
  while(!myqueue.empty())//队列清空
   myqueue.pop();
  for (i=1;i<m+1;i++)
   pre[i]=-1;//pre[i]=-1表示该点没有入队
  pre[src]=0;
  flow[src]=maxdata;
  myqueue.push(src);
  while (!myqueue.empty())
   {
    int index=myqueue.front();
    myqueue.pop();
    if (index==des)//index==des说明所有到终点的路已经都搜索完了
     break;
    for (i=1;i<m+1;i++)
     {
      if (i!=src&&capacity[index][i]>0&&pre[i]==-1)//i不是源点,且从当前点可以到达i点,i点不在队列中,则i点入队
      {
      pre[i]=index;//该路径上i的前驱点为index
      flow[i]=min(capacity[index][i],flow[index]);//要通过必须满足流量小于等于所有边的最小值
      myqueue.push(i);
      }
     }
   }
   if (pre[des]==-1)
    return -1;
   else
    return flow[des];
}
int maxflow(int src,int des)//src表示源点,des表示汇点
{
int increasement=0;
int sumflow=0;
while((increasement=bfs(src,des))!=-1)//有可以流到汇点的路径
{
int k=des;
while (k!=src)
{
int last=pre[k];
capacity[last][k]-=increasement;//用路径上每一条边的容量减去该路径的流量
capacity[k][last]+=increasement;//给程序反悔和改正的机会
k=last;
}
sumflow+=increasement;
}
return sumflow;
}
int main()
{
freopen("b.in","r",stdin);
freopen("b.out","w",stdout);
int i,j,l;
int start,end,ci;
    cin>>m>>n;
memset(capacity,0,sizeof(capacity));
memset(flow,0,sizeof(flow));
for (i=1;i<=n;i++)
{
cin>>start>>end>>ci;
x[i]=start; y[i]=end; len[i]=ci;
if (start==end)
continue;
c[start][end]=capacity[start][end]+=ci;
c[end][start]=capacity[end][start]+=ci;
}
    scanf("%d",&p);
    for (l=1;l<=p;l++)
     {
      int x1,y1,z1;
      for (i=1;i<=m;i++)
      for (j=1;j<=m;j++)
       capacity[i][j]=c[i][j];
      scanf("%d%d%d",&x1,&y1,&z1);
      if (x1==0)
      printf("%d\n",maxflow(y1,z1));
      if (x1==1)//改变编号Y1的边的容量,
      {
      c[x[y1]][y[y1]]=capacity[x[y1]][y[y1]]=z1;
      c[y[y1]][x[y1]]=capacity[y[y1]][x[y1]]=z1;
      }
     }
}//如果把网络流的图看作一系列的管道,那么求最大流就相当于从源点处注水,求最多最终有多少水可以流到汇点
0 0