POJ1459Power Network(最大流)

本文介绍了一道关于电力网络的最大流问题,通过增加超级源点和超级汇点将多源多汇的问题转化为标准的最大流问题,并给出了具体的C++实现代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  • 题意: 
    简单的说下题意(按输入输出来讲,前面的描述一堆的rubbish,还用来误导人),给你n个点,其中有np个是能提供电力的点,nc个是能消费电力的点,剩下的点(n-np-nc)是中转战即不提供电力也不消费电力,点与点之间是有线路存在的,有m条线路,每条线路有最多运载限定。 
    前4个数据就是有n个点,np个供电点,nc个消费点,m条线路,接来题目先给出的是m条线路的数据,(起点,终点)最多运载量,然后是np个供电点的数据(供电点)最多供电量,接着就是nc个消费点的数据(消费点)最多消费电量。 
    题目要我们求出给定的图最大能消费的总电量(就是求最大流)

  • 思路: 
    供电点有提供功能,那么供电点就可以当成源点,同样消费点有消费功能,可以当成汇点。 
    由于这题有多个供电点和消费点,我们可以增加两个点,一个超级源点和一个超级汇点。 
    把所有的供电点都当成是由超级源点提供电量的,所有的消费点都将消费电量转移到超级汇点上,这样就相当于转换成一个基本的网络流求最大流的题。 
    超级源点与供电点有一条边,边的值为供电点最大能提供的电量,消费点与超级汇点有一条边,边的值为消费点最大能消费的电量。


#include<iostream>
#include<cstdio>
#include<climits>
#include<cstring>
#include<queue>
using namespace std;
const int maxn = 105;
const int MAXINT = INT_MAX;
typedef struct
{
    int flow;       //流量
    int capacity;   //最大容量值
}Edge;
Edge edge[maxn][maxn];
int vertime;        //顶点总数
int nedges;         //边的总数
int power_stations; //发电站总数
int consumers;      //消费者总数
int maxflow;        //最大流
int sp, fp;         //标记源点与汇点
int parent[maxn];   //用于bfs寻找路径
int bfs(int start, int _end)
{
    int res[maxn];
    queue<int> q;
    memset(res, 0, sizeof(res));
    memset(parent, -1, sizeof(parent));
    q.push(start);
    res[start] = MAXINT;
    while(!q.empty())
    {
        int u = q.front();
        q.pop();
        for(int v = 1; v <= vertime; v++)
        {
            if(!res[v] && edge[u][v].capacity > edge[u][v].flow)
            {
                q.push(v);
                parent[v] = u;
                res[v] = min(res[u], edge[u][v].capacity - edge[u][v].flow);
            }
        }
        if(u == _end)
            break;
    }
    return res[_end];
}
void EdmondsKarp()
{
    int tmp;
    maxflow = 0;
    while(tmp = bfs(sp, fp))
    {
        for(int i = fp; i!= sp; i = parent[i])
        {
            edge[parent[i]][i].flow += tmp;     //更新正向流
            edge[i][parent[i]].flow -= tmp;     //更新反向流
        }
        maxflow += tmp;
    }
}
int main()
{
    int u, v, w;
    char ch;
    while(scanf("%d%d%d%d", &vertime, &power_stations, &consumers, &nedges) != EOF)
    {
        memset(edge, 0, sizeof(edge));
        for(int i = 1; i <= nedges; i++)    //设置读图从1开始
        {
            cin >> ch >> u >> ch >> v >> ch >> w;
            edge[u+1][v+1].capacity = w;
        }
        sp = vertime + 1, fp = vertime + 2, vertime += 2;
        for(int i = 1; i <= power_stations; i++)    //建立超级源点指向所有的发电站
        {
            cin >> ch >> v >> ch >> w;
            edge[sp][v+1].capacity = w;
        }
        for(int i = 1; i <= consumers; i++)         //建立超级汇点,使所有消费者指向它
        {
            cin >> ch >> v >> ch >> w;
            edge[v+1][fp].capacity = w;
        }
        EdmondsKarp();
        printf("%d\n", maxflow);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值