poj 1459 (简单网络流)

题目链接:poj 1459

参考题意博客:https://blog.csdn.net/huangshuai147/article/details/51179586

Sample Input

2 1 1 2 (0,1)20 (1,0)10 (0)15 (1)20
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

这题目又臭又长,参考此博客题意:

前四个数分别表示,m个点,np个发电站,nc个用户,n条边 
    接下去是n条边 ------(u,v)w,w表示边(u,v)的最大流量;
    np个发电站---(u)w,w表示发电站u能提供的最大流量;
    nc个用户的信息(v)w,w表示每个用户v能接受的最大流量。

 

解题思路:对于这道题我们建立一个超级源点超级汇点,所谓超级源点指的是所有发电站发电量的总和超级汇点指的是所有用户接受的电量总和,对此我们建立0为超级源点,m+1为超级汇点,其余的按输入存储就行了,还有一个题目的点是从0开始的,而我们没有-1的点来做超级源点,故我们把题目输入的点都往后移一位。

///简单网络流变形

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;

typedef long long LL;
#define INF 0x3f3f3f3f

const int maxn=105;
int capacity[maxn][maxn];
int flow[maxn];
int pre[maxn];
int n,m;

queue <int> myqueue;

int BFS(int src,int des)
{
    while(!myqueue.empty())
        myqueue.pop();

    memset(pre,-1,sizeof(pre));

    pre[src]=0;
    flow[src]=INF;

    myqueue.push(src);

    while(!myqueue.empty())
    {
        int index=myqueue.front();
        myqueue.pop();

        if(index==des) break;

        for(int i=0;i<=des;i++) ///从源点到目标循环
        {
            if(i!=src&&capacity[index][i]>0&&pre[i]==-1)
            {
                pre[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) ///EK模板
{
    int increase=0;
    int sumflow=0;

    while((increase=BFS(src,des))!=-1)
    {
        int k=des;

        while(k!=src)
        {
            int last=pre[k];
            capacity[last][k]-=increase;
            capacity[k][last]+=increase;
            k=last;
        }
        sumflow+=increase;
    }

    return sumflow;
}
int main()
{
    int a,b;

    while(~scanf("%d%d%d%d",&n,&a,&b,&m))
    {
        memset(capacity,0,sizeof(capacity));

        int u,v,w;
        for(int i=1;i<=m;i++)
        {
            scanf(" (%d,%d)%d",&u,&v,&w);
            if(u!=v) capacity[++u][++v]=w; 
        }

        for(int i=1;i<=a;i++)
        {
            scanf(" (%d)%d",&u,&w);
            capacity[0][++u]=w; ///因为发电站的点可以是0,而我们希望0作为超级源点,故都往后移一位
        }

        for(int i=1;i<=b;i++)
        {
            scanf(" (%d)%d",&v,&w);
            capacity[++v][n+1]=w;
        }



        printf("%d\n",maxFlow(0,n+1));
    }
    return 0;
}














 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值