poj1459Power Network_最大流的增广路算法_多源点多汇点问题(Edmord_Karp)

题目要求通过建立发电站到用户的电力输送网络,解决最大电力输送问题。此问题可转化为最大流的多源多汇点模型。解题方法是添加超级源点和超级汇点,利用最大流增广路算法求解。在输入数据处理时,需要注意避免因额外字符导致的读入错误,确保数据输入的准确性。

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

题目链接

题目大意:

现在有一个发电站,需要给用户送电。

解释一下输入数据:

总结点数 nodenum  电站数power   用户数consumer  电缆线数link

然后link行,起点-终点 发电量

然后power行,每个电站的产电量

然后consumer行,每个用户的用电量

解题思路:

这道题是最大流的入门题,只是变成了多源多汇。这个模型非常经典,只需要添加一个超级源点和一个超级汇点就变成了普通的最大流模型。



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

Sample Output

15
6
一个投机取巧就是在读取数据(0,1)20的时候是用的scanf(" (%d%d)%d",&u,&v,&cost);

一般在scanf读入数据的时候是最好不好加入别的字符的,因为可能会造成读入数据出错。因为有字符串的存在,所以在(%d%d)前面加上一个空格符号,如果运行后得不到答案,可以输出一下你输入的数据进行测试,首先要保证输入正确。这里也可以用一个字符串来处理数据(但是比较麻烦了);

用的算法还是那个最大流增广路的算法,这个模板是个好东西。。。。

加入了一个超级源点和超级汇点,因为原来的节点是从0开始的,为了好处理,我们让每个节点+1,让它节点变成是从1开始的,又因为我们自己加入了一个超级源点,所以每个节点又+1(超级源点就是1),那么超级汇点就是总的节点个数了。

#include<stdio.h>
#include<queue>
#include<string.h>
#define inf 1<<28
#define min(a,b) a<b?a:b
using namespace std;
 
int start,end;
int map[105][105];
int flow[105];
int path[105];


int bfs()
{
  memset(path,-1,sizeof(path));
  int i,u;
  queue<int>Q;
  path[start]=0;
  flow[start]=inf;
  Q.push(start);
  
  while(!Q.empty())
  {
    u=Q.front();
	Q.pop();
	
	if(u==end) break;
	
	for(i=start;i<=end;i++)
	{
		if(i!=start && path[i] == -1 && map[u][i])
		{
		
			flow[i]=min(flow[u],map[u][i]);	
			path[i]=u;
			Q.push(i);
		}
	}	
  }	
  
  if(path[end]==-1)return -1;
  return flow[end];
}
int Edmords_Karp()
{
    int max_flow=0,ff,now,pre;
    memset(flow,0,sizeof(flow));
    
	while((ff=bfs())!=-1)
	{
		max_flow+=ff;
		now=end;
		
		while(now != start)
		{					
			pre=path[now];
	    	map[pre][now]-=ff;
			map[now][pre]+=ff;
			now=pre;
		}
		
	}	
	return max_flow;
}
int main()
{
	int power,consumer,link,u,v,num,cost;
	int i,j;
	
	while(~scanf("%d%d%d%d",&num,&power,&consumer,&link))
	{
		num=num+2;
		
		memset(map,0,sizeof(map));
		
		for(i=0;i<link;i++)
		{
			scanf(" (%d,%d)%d",&u,&v,&cost);
			u+=2;
			v+=2;
			map[u][v]+=cost;
		}
		
		for(i=0;i<power;i++)
		{
			scanf(" (%d)%d",&u,&cost);
			u+=2;
			map[1][u]+=cost;
		}
		
		for(i=0;i<consumer;i++)
		{
			scanf(" (%d)%d",&v,&cost);
			v+=2;
			map[v][num]+=cost;
		}
		
		start=1;
		end=num;
		

		     
		int res=Edmords_Karp();
		printf("%d\n",res);
	}
	
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值