网络流算法集合 EK dinic 最小费用最大流 (Dijkstra实现)

终于快把网络流的模板写完了,先贴几个,存边用前向星实现,既保证了速度又免去了写链表的麻烦,代码绝对是你能找到的代码中最精简的

//EK
#include
#include
using namespace std;
#include
#define MAXN 300
#define MAXFLOW 2000000000
int n,s,t,m,flow[MAXN+1][MAXN+1],map[MAXN+1][MAXN+1],pre[MAXN+1];
void init()
{
  int i,a,b,c;
  memset(map,0,sizeof(map));
  memset(flow,0,sizeof(flow));
  memset(pre,0,sizeof(pre));
  cin>>n>>s>>t>>m;
  for(i=1;i<=m;i++)
  {
 cin>>a>>b>>c;
 map[a][0]++;
 map[a][map[a][0]]=b;
        map[b][0]++;
        map[b][map[b][0]]=a;
        flow[a][b]+=c;//对于重边的存在,推荐用+=
  }
}
int bfs()
{
  int i,tt[MAXN+1],start,finish,chk[MAXN+1],k;
  memset(tt,0,sizeof(tt));
  memset(chk,0,sizeof(chk));
  start=1;finish=1;tt[1]=s;
  while(start<=finish)
  {
    for(i=1;i<=map[tt[start]][0];i++)
   if ((!chk[map[tt[start]][i]])&&(flow[tt[start]][map[tt[start]][i]]))
   {
    k=map[tt[start]][i];
    finish++;
    tt[finish]=k;
    chk[k]=1;
    pre[k]=tt[start];
    if(k==t) return 1;
   }
  start++;
  }
 return 0;

}
int min(int a,int b)
{
  if (a    else return b;
}
int main()
{
  int ans,k,v;
  init();
  ans=0;
  while (bfs())
  {
    k=t;v=MAXFLOW;
    while(k!=s)
 {
      v=min(v,flow[pre[k]][k]);
   k=pre[k];
 }
    k=t;ans+=v;
      while(k!=s)
 {
     flow[pre[k]][k]-=v;
  flow[k][pre[k]]+=v;
     k=pre[k];
 }
  }
 cout<}

 

 

 

//最大流 Dinic 比EK多写了个函数 用来计算源点到这个点经过的最少边数 加了个判断条件

#include
#include
using namespace std;
#include
#define MAXN 300
#define MAXFLOW 2000000000
int n,s,t,m,flow[MAXN+1][MAXN+1],map[MAXN+1][MAXN+1],pre[MAXN+1],d[MAXN+1];
void init()
{
  int i,a,b,c;
  memset(map,0,sizeof(map));
  memset(flow,0,sizeof(flow));
  memset(pre,0,sizeof(pre));
  for(i=1;i<=m;i++)
  {
 cin>>a>>b>>c;
 map[a][0]++;
 map[a][map[a][0]]=b;
        map[b][0]++;
        map[b][map[b][0]]=a;
        flow[a][b]+=c;
  }
}
void Re_d()
{
  int i,j,a[300],start,final,cur;
  memset(d,0,sizeof(d));
  start=1;final=1;
  d[s]=1;
  a[1]=s;
  while(start<=final)
  {
    cur=a[start++];
     for(i=1;i<=map[cur][0];i++)
      {
        j=map[cur][i];
  if ( (flow[cur][j]>0)
   && (!d[j]) )
  {
    d[j]=d[cur]+1;
    a[++final]=j;
  }
      } 
  }
}
int bfs()
{
  int i,tt[MAXN+1],start,finish,chk[MAXN+1],k;
  memset(tt,0,sizeof(tt));
  memset(chk,0,sizeof(chk));
  start=1;finish=1;tt[1]=s;
  while(start<=finish)
  {
    for(i=1;i<=map[tt[start]][0];i++)
   if ((!chk[map[tt[start]][i]])&&(flow[tt[start]][map[tt[start]][i]])&&(d[tt[start]]+1==d[map[tt[start]][i]])) 

                                                                                               //(d[tt[start]+1==d[map[tt[start]][i]])加这个条件
   {
    k=map[tt[start]][i];
    finish++;
    tt[finish]=k;
    chk[k]=1;
    pre[k]=tt[start];
    if(k==t) return 1;
   }
  start++;
  }
 return 0;
}
int min(int a,int b)
{
  if (a    else return b;
}
int main()
{
  int ans,k,v;
while(cin>>m>>n)
{
 s=1;t=n;
//cin>>s>>t;//s,t是源点和汇点
  init();
  ans=0;
  Re_d();
  while (bfs())
  {
    k=t;v=MAXFLOW;
    while(k!=s)
 {
          v=min(v,flow[pre[k]][k]);
   k=pre[k];
 }
      k=t;ans+=v;
      while(k!=s)
 {
         flow[pre[k]][k]-=v;
  flow[k][pre[k]]+=v;
         k=pre[k];
 }
     Re_d();
  }
 cout<}
}

 

//最小费用最大流 (Dijkstra实现)
#include
#include
#include
using namespace std;
#define MAXN 300
#define MAXFlow 2000000
#define MAXV 200000000
int n,s,t,m,k,Flow[MAXN+1][MAXN+1],map[MAXN+1][2*MAXN+1],pre[MAXN+1],d[MAXN+1],Fee[MAXN+1][MAXN+1],d0[MAXN+1];
//Flow流量,Fee价值,map用记录儿子的形式存边,pre[i]i的前继
bool init()
{
 int i,a,b,j,fee,u,v,l,c;
 memset(map,0,sizeof(map));
 memset(Flow,0,sizeof(Flow));
 memset(pre,0,sizeof(pre));
 for(i=0;i<=MAXN;i++)
  d[i]=MAXV;
 for(i=0;i<=MAXN;i++)
  for(j=0;j<=MAXN;j++)
  {
   Fee[i][j]=MAXV;
  }
  cin>>n>>m>>s>>t;
 if ((n==0)&&(m==0)&&(k==0)) return false;
        for(i=1;i<=m;i++)
         {
    cin>>a>>b>>c>>fee;
    map[a][0]++;
    map[a][map[a][0]]=b;
           map[b][0]++;
           map[b][map[b][0]]=a;
           Flow[a][b]=c;
     Fee[a][b]=fee;
     Fee[b][a]=-fee;
         }
        d[s]=0;
 return true;
}
int dijkstra()
{
 int i,tt[MAXN+1],chk[MAXN+1],k,min_d,j,min_i,ft;
 memset(tt,0,sizeof(tt));
 memset(chk,0,sizeof(chk));
 for(i=0;i<=MAXN;i++)
  d[i]=MAXV;
 d[s]=0;
 ft=0;
 min_i=MAXV;
 for(j=1;j<=n;j++)
 {
  min_d=MAXV;
  for(i=1;i<=n;i++)
   if ((!chk[i])&&(d[i]   {
    min_i=i;
    min_d=d[i];
   }
   if (min_d==MAXV) break;
   chk[min_i]=1;
   for(i=1;i<=map[min_i][0];i++)
    if (Flow[min_i][map[min_i][i]]>0)
    {
     k=map[min_i][i];
     if (d[k]>(d[min_i]+Fee[min_i][k]-d0[min_i]+d0[k]))
     {
      d[k]=d[min_i]+Fee[min_i][k]-d0[min_i]+d0[k];
      pre[k]=min_i;
     }
    }
 }
 return (d[t]!=MAXV);
}
void re_D()
{
 int i;
 for(i=0;i<=n;i++) d0[i]=-d[i];
}
int min(int a,int b)
{
 if (a    else return b;
}
int main()
{
 int ans,k,v,st;
  while(init())
  {
 ans=0;
 memset(d0,0,sizeof(d0));
 while (dijkstra())
 {
  k=t;v=MAXFlow;
  while(k!=s)
  {
   v=min(v,Flow[pre[k]][k]);
   k=pre[k];
  } 
  k=t;ans+=v*(d[t]-d0[t]);
  while(k!=s)
  {
   Flow[pre[k]][k]-=v;
   Flow[k][pre[k]]+=v;
   k=pre[k];
  }
  re_D();
 }
 cout<  }
 return 0; 
}

 

 

 

你可能感兴趣的:(偶滴ACM)