POJ1459(Power Network)【网络流】

题目链接:http://poj.org/problem?id=1459

题意:有N个电站,M条线路,P个发电站,C个用电站,(N-P-C)个中转站,题目先给出M条线路的情况,格式如下:(起点,终点)最大流量。然后是发电站和用电站的情况,格式为(电站序号)最大发电量或用电量。求最大消耗的电能。

思路:我们可以设置一个超级源点和一个超级汇点,源点与所有发电站相连,最大流量为发电站的发电量,汇点与所有用电站相连,最大流量为用电站最大用电量,然后用EK算法求最大流即可。另外,题目的读入格式略有点恶心,需要小心read()表示不知道你在说些什么

#include<queue>
#include<cstdio>
#include<string>
#include<cstring>
using namespace std;
const int maxn=505,INF=1e10;
int N,P,C,M,tot,ed,hed,til,map[maxn][maxn],fa[maxn],que[maxn];
bool vis[maxn];
inline int read() {
	int ret=0,f=1;char ch=getchar();
	for (; !isdigit(ch); ch=getchar()) if (ch=='-') f=-f;
	for (; isdigit(ch); ch=getchar()) ret=ret*10+ch-48;
	return ret*f;
}
inline int EK() {
//	一定要用BFS来求增广路,用DFS的求法叫FF算法,虽然同样是O(N*M^2)但EK更快,不会超时。 
	int ans=0;
	for (; ; ) {
		memset(fa,-1,sizeof fa);
		memset(vis,0,sizeof vis);
		hed=0,til=1;
		que[1]=0,vis[0]=0;
		while (hed<til) {
			int t=que[++hed];
			if (t==ed) break;
			for (int i=1; i<=ed; i++) if (!vis[i]&&map[t][i])
				fa[i]=t,vis[i]=1,que[++til]=i;
		}
		if (!vis[ed]) return ans;
		int minv=INF;
		for (int i=ed; i; i=fa[i]) minv=min(minv,map[fa[i]][i]);
		for (int i=ed; i; i=fa[i]) map[fa[i]][i]-=minv,map[i][fa[i]]+=minv;
		ans+=minv;
	}
}
int main() {
	while (~scanf("%lld%lld%lld%lld",&N,&P,&C,&M)) {
		tot=0,ed=N+1;
		memset(map,0,sizeof map);
		for (int i=1; i<=M; i++) {
			int x=read()+1,y=read()+1,z=read();
			map[x][y]=z;
		}
		for (int i=1; i<=P; i++) {
			int y=read()+1,z=read();
			map[0][y]=z;
		}
		for (int i=1; i<=C; i++) {
			int x=read()+1,z=read();
			map[x][ed]=z;
		}
		printf("%d\n",EK());
	}
	return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值