最大流模型 解决poj 1459 电力网络

题意:给定若干个发电站及其发电量和若干中间传输节点和若干消费者及其消费量,以及节点之间传输的容量限制,求从发电站到消费者最大的传输电量。

思路:典型的最大流问题,由于有多个发电站和多个消费者,不妨构建一个超级发电站和一个超级消费者。即将超级发电站与各个发电站相连,连接的容量即为各个发电站的发电量,将各个消费者与超级消费者相连,连接的容量即为各个消费者的消费量。

例如数据:

7 2 3 13 (0,0)1 (0,1)2 (0,2)5 (1,0)1 (1,2)8 (2,3)1 (2,4)7

(3,5)2 (3,6)5 (4,2)7 (4,3)5 (4,5)1 (6,0)5

(0)5 (1)2 (3)2 (4)1 (5)4

首先利用数据构建残存网络,超级发电站为7,超级消费者为8:

image 图1

见图1中红色的边,由于我们的最大流算法采用广度优先搜索,红色的边在广度优先搜索中是用不到的,所以忽略。接下来找到一条增广路径,如图2中的红色路径(最大流增加1),图3表示根据增广路径更新以后的残存网络。

image图2 image 图3

依次更新残存网络,并且找到一条增广路径,同时最大流增加相应的流量,直到找不到增广路径为止,如下图4所示,左边的图为寻找增广路径,右边的图为根据增广路径更新以后的残存网络,看图顺序为从左向右、自上而下(显然不同的查找顺序,所找到的增广路径也不相同,我只选择其中的一种情况)

image 图4

最终最大流为1+2+1+1+1=6。

CODE:

 
 
 
#include<iostream> 
#include<queue> 
#define MAXN 1000 
#define INF 10000000 
using namespace std; 
//编写最大流程序 利用残存网络 
//处理的问题是 电力网络  
 
int Gf[MAXN][MAXN]; 
//记录每个节点的前驱 用于记录路径 
int pre[MAXN]; 
//给节点做标记 
int flag[MAXN]; 
//设定s为n,t为n+1; 
 
int start,end;//存储起点和终点 
//输入数据 
int n,np,nc,m; 
//最大流为0 
int maxf=0; 
void init() 
{ 
      maxf=0; 
      start=n;end=n+1; 
      //首先初始化残存网络 都为0 
      memset(Gf,0,sizeof(Gf)); 
      //首先输入m条边 
      for(int i=0;i<m;i++) 
      { 
         int u,v,w; 
         scanf(" (%d,%d)%d",&u,&v,&w); 
         //in>>c>>u>>c>>v>>c>>w; 
         Gf[u][v]=w; 
      } 
      //输入发电站 
      for(int i=0;i<np;i++) 
      { 
         int id,w; 
         scanf(" (%d)%d",&id,&w); 
         Gf[start][id]=w; 
      } 
      //输入消费者 
      for(int i=0;i<nc;i++) 
      { 
         int id,w; 
         scanf(" (%d)%d",&id,&w); 
         Gf[id][end]=w; 
      } 
} 
 
void modify() 
{ 
      int minw=INF; 
      int u=end; 
      while(pre[u]!=-1) 
      { 
         minw=min(minw,Gf[pre[u]][u]); 
         u=pre[u]; 
      } 
      u=end; 
      while(pre[u]!=-1) 
      { 
         Gf[pre[u]][u]-=minw; 
         Gf[u][pre[u]]+=minw; 
         u=pre[u]; 
      }  
      maxf+=minw; 
} 
 
//EK   利用广度优先搜索寻找最大流 
void EK() 
{ 
   while(1) 
   { 
   //初始化前驱数组 
   memset(pre,-1,sizeof(pre)); 
   memset(flag,0,sizeof(flag)); 
   //flag[s]=1; 
   queue<int>q; 
   q.push(start); 
   flag[start]=1; 
   int ok=0; 
   while(!q.empty()) 
   {  
      int u=q.front(); 
      q.pop(); 
      if(u==end) 
      { 
         ok=1; 
         break; 
      } 
      //flag[u]=1; 
      for(int v=0;v<=n+1;v++) 
      { 
         if(!flag[v]&&Gf[u][v]>0) 
         { 
            flag[v]=true; 
            q.push(v); 
            pre[v]=u; 
         } 
      }  
   } 
   if(ok) 
   { 
      //重构残存网络 
      modify(); 
   } 
   else 
   { 
      break; 
   } 
} 
} 
int main() 
{ 
    while(cin>>n>>np>>nc>>m) 
    { 
        init();  
        EK(); 
        cout<<maxf<<endl;                  
    } 
   // system("pause"); 
    return 0; 
} 
/* 
7 2 3 13 (0,0)1 (0,1)2 (0,2)5 (1,0)1 (1,2)8 (2,3)1 (2,4)7 
(3,5)2 (3,6)5 (4,2)7 (4,3)5 (4,5)1 (6,0)5 
(0)5 (1)2 (3)2 (4)1 (5)4 
2 1 1 2 (0,1)20 (1,0)10 (0)15 (1)20 
*/ 
 

posted @ 2013-06-14 20:17  Penseur  阅读(344)  评论(0编辑  收藏