poj1459——Power Network

题目大意:网络图中有n个结点,其中有np个发电站,nc个耗电站,还有n-np-nc个中转站,给出m条输电线,每个输电线上的运送电量为l(u,v),意为uv结点间的输电量,p(u)代表u结点的产电量,c(u)代表u结点的耗电量,s(u)代表给u结点的供电量,d(u)=s(u)+p(u)-c(u),代表能从u结点输出的电量,规定发电站的c(u)=0,耗电站的p(u)=0,中转站的p(u)=c(u)=0。问所有耗电站总耗电的最大值。

输入:(可以有很多个case)

            n  np  nc  m  (u,v)lmax(u,v)(共m个)  (u)pmax(u)(共np个)  (u)cmax(u)(共nc个)

输出:最大耗电量

分析:最大流的增广路算法(EK算法即最短路径增广算法)。

           增广路定理:网络达到最大流<=>残留网络中没有增广路

           如何找增广路:bfs搜索找出这样的路径,路径上每一条边都要满足容量-流量>0

           找出增广路上容量的最小值,将每条边的容量都减去这个值,并且在增广路上的每条反向边也要加上这个值(为了做到这个bfs时要记录前驱),要求的最大流也加上这个值。最终找不到增广路时就得出了最大流。

代码:转载自http://124654439.iteye.com/blog/2101140

  1. #include<iostream>  
  2. #include<queue>  
  3. using namespace std;  
  4. #define MAXSIZE 130  
  5. int map[MAXSIZE][MAXSIZE];  
  6. int pre[MAXSIZE];  
  7. queue<int>que;  
  8. int n,np,nc,m;  
  9. int bfs(int src,int dec)//源点和汇点  
  10. {  
  11.     memset(pre,-1,sizeof(pre));  
  12.     while(!que.empty())que.pop();  
  13.     pre[src]=src;  
  14.     que.push(src);  
  15.     int temp;  
  16.     while(!que.empty())  
  17.     {  
  18.         temp=que.front();  
  19.         que.pop();  
  20.         if(temp==dec)  
  21.             break;  
  22.         for(int i=0;i<n+2;i++)  
  23.         {  
  24.             if(map[temp][i]&&pre[i]==-1)//如果有路径 并且 还没有用过  
  25.             {  
  26.                 pre[i]=temp;  
  27.                 que.push(i);  
  28.             }  
  29.         }  
  30.     }  
  31.       
  32.     if(temp==dec)  
  33.         return 1;  
  34.     else   
  35.     return 0;  
  36. }  
  37.   
  38. int maxFlow(int src,int dec)  
  39. {  
  40.     int ans=0;  
  41.     while(bfs(src,dec))  
  42.     {  
  43.         int i;  
  44.         int min=999999;  
  45.         for(i=dec;i!=src;i=pre[i])  
  46.         {  
  47.             min=min>map[pre[i]][i]?map[pre[i]][i]:min;  
  48.         }  
  49.   
  50.         for(i=dec;i!=src;i=pre[i])  
  51.         {  
  52.             map[pre[i]][i]-=min;  
  53.             map[i][pre[i]]+=min;  
  54.         }  
  55.         ans+=min;  
  56.     }  
  57.   
  58.     return ans ;  
  59. }  
  60.   
  61.   
  62. int main()  
  63. {  
  64.     int i;  
  65.     char ss[50];  
  66.     int a,b,c;  
  67.     int src,dec;  
  68.     while(scanf("%d%d%d%d",&n,&np,&nc,&m)!=EOF)  
  69.     {  
  70.         memset(map,0,sizeof(map));  
  71.         src=n;  
  72.         dec=n+1;  
  73.         for(i=0;i<m;i++)  
  74.         {  
  75.             scanf("%s",ss);  
  76.             sscanf(ss,"(%d,%d)%d",&a,&b,&c);  
  77.             map[a][b]=c;  
  78.         }  
  79.         for(i=0;i<np;i++)  
  80.         {  
  81.             scanf("%s",ss);  
  82.             sscanf(ss,"(%d)%d",&a,&b);  
  83.             map[src][a]=b;  
  84.         }  
  85.         for(i=0;i<nc;i++)  
  86.         {  
  87.             scanf("%s",ss);  
  88.             sscanf(ss,"(%d)%d",&a,&b);  
  89.             map[a][dec]=b;  
  90.               
  91.         }  
  92.         printf("%d\n",maxFlow(src,dec));  
  93.     }  
  94.   
  95.       
  96.     return  0;  
  97. }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值