POJ1459 Power Network (SAP+GAP优化)

题目大意:就是有发电站、用户、中转站,还有电力传输路线,每个节点有可能被传输了多少电,也可能消耗了多少电,也可能生产了多少电,也可能传输了多少电。发电站除了生产电之外都可能会。

用户除了生产电之外都可能会,而中转站只会传输电和被传输电。求电力消耗的最大值。

思路:建立一个超级源点和所有发电站连接起来,建立一个超级汇点和所有用户连接起来,那么这个图的最大流即是最大消耗量。

想象一下,在复杂的地下水管道下面,在源点流入了一股定量的水,那么能够到达汇点的即是能够达到每位用户的总和,而我们现在就是要求这个总和 的最大值。

我是用SAP+GAP优化的模板撸过的~~第一次敲这个模板竟然忘了反向边。囧。。而且更忘了反向边 容量值是0。囧。。

AC program:

#include<iostream>
#include<stdio.h> 
#include<string.h> 
#include<math.h>
#include<queue>  
#include<algorithm>
using namespace std;
#define inf 1000000000
#define maxn 150
#define maxm 20500  //note!! 如果RE就是这里出的原因 
int num;//note1 
int n,np,nc,m;
struct node
{
  int c,next,to;       
}e[maxm]; //note2 
int box[maxn];//链式前向星 
void init1()
{
    num=0;
    memset(box,-1,sizeof(box));//按道理应该是初始化为-1的 
    //int aa,bb,w,u,v;
    int u,v,w; 
    char yy[20];                                       
    for(int i=1;i<=m;i++)
    {       
                                       
      scanf("%s",yy); 
      sscanf(yy,"(%d,%d)%d",&u,&v,&w); 
      u+=2;//统一加2
      v+=2; 
      e[num].to=v;
      e[num].c=w;
      e[num].next=box[u];
      box[u]=num;
      num++; 
      ///-------
      e[num].to=u;
      e[num].c=0;//note!! 
      e[num].next=box[v];
      box[v]=num;
      num++; 
      ///-------
          
    }
    for(int i=1;i<=np;i++)
    {
                                       
       scanf("%s",yy);
       sscanf(yy,"(%d)%d",&v,&w);
       u=1; //原点设为1,所以原来的点要往后推2 
       v+=2;
       e[num].to=v;
       e[num].c=w;
       e[num].next=box[u];
       box[u]=num;
       num++;
       ///-------
       e[num].to=u;
       e[num].c=0;//note!! 
       e[num].next=box[v];
       box[v]=num;
       num++; 
       ///-------       
    }
    for(int i=1;i<=nc;i++)
    {
                                       
       scanf("%s",yy);
       sscanf(yy,"(%d)%d",&u,&w);
       u+=2;
       v=n+2;
       e[num].to=v;
       e[num].c=w;
       e[num].next=box[u];
       box[u]=num;
       num++;
       ///-------
       e[num].to=u;
       e[num].c=0;//note!! 
       e[num].next=box[v];
       box[v]=num;
       num++; 
       ///-------       
    }    
}
int sap(int start,int end,int nnn)
{
  int numh[maxn],h[maxn],cur[maxn],pre[maxn];
  int cur_flow,flow_ans=0,u,tmp,neck,i;
  memset(h,0,sizeof(h)); 
   memset(numh,0,sizeof(numh));///
     memset(pre,-1,sizeof(pre));///
  for(int i=1;i<=nnn;i++)
     cur[i]=box[i];
  numh[0]=nnn;
  u=start;
  while(h[start]<nnn)
  {
      if(u==end)
      {
          cur_flow=inf;
          for(i=start;i!=end;i=e[cur[i]].to)
          {
              if(cur_flow>e[cur[i]].c)
              {
                neck=i;
                cur_flow=e[cur[i]].c;                        
              }                                  
          }
          for(i=start;i!=end;i=e[cur[i]].to)
          {
            tmp=cur[i];
            e[tmp].c-=cur_flow;
            e[tmp^1].c+=cur_flow;                                  
          }
          flow_ans+=cur_flow;
          u=neck;          
      }
      for(i=cur[u];i!=-1;i=e[i].next)
          if(e[i].c&&h[u]==h[e[i].to]+1) 
             break;
      if(i!=-1)
         {
               
           cur[u]=i;
           pre[e[i].to]=u;
           u=e[i].to;      
         }
      else
          {
            if(0==--numh[h[u]])break;
            cur[u]=box[u];
            for(tmp=nnn,i=box[u];i!=-1;i=e[i].next)
                if(e[i].c)
                    tmp=min(tmp,h[e[i].to]);
            h[u]=tmp+1;
            ++numh[h[u]];
            if(u!=start)u=pre[u];                 
                           
          } 
                                       
                        
  } 
  return flow_ans; 
} 
int main()
{
while(scanf("%d%d%d%d",&n,&np,&nc,&m)!=EOF)
{
    init1();
    int love;
    love=sap(1,n+2,n+2);//n+2个点 
    printf("%d\n",love);                                         
} 
//system("pause"); 
return 0;} 



 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值