「转载」最大流

newtee 2012-07-12 02:58:59

/*
题目:poj 1273 Drainage Ditches (网络流最大流)
题意:
有n道水渠,和m个节点,其中每道水渠都有一个最大流
问从1节点到m节点的最大流
Sample Input
5 4
1 2 40
1 4 20
2 4 20
2 3 30
3 4 10
Sample Output
50
解题:
最大流 利用 edmonds_karp算法 bfs
*/
#include<stdio.h>
#include<string.h>
#define M 230
#define INF 0x7FFFFFFF
#define min(a,b) a<b?(a):(b)
/* f[i]存储第i点存储的水 residual[i][j]存储从i到j水渠的剩余流量 pre存储前驱节点*/
int residual[M][M],pre[M],f[M],q[M];
int n,m;
void input()
{
int x,y,z;
memset(residual,0,sizeof(residual));
for(int i=0;i<n;i++)
{
scanf("%d%d%d",&x,&y,&z);
residual[x][y]+=z;/* 因为存在回路 */
}
}
int bfs()
{
for(int i=1;i<=m;i++)
f[i]=INF;
q[0]=1;
memset(pre,-1,sizeof(pre));
int head=-1,tail=0,cur;
while(head<tail)
{
++head;
cur=q[head];
if(cur==m)
return f[m];
for(int i=1;i<=m;i++)
{
/*如果该点已经走过或者从cur到i的水渠的流量为0时*/
if(pre[i]!=-1||residual[cur][i]==0)
continue;
pre[i]=cur;
f[i]=min(f[cur],residual[cur][i]);
++tail;
q[tail]=i;
}
}
return -1;
}
int EK()
{
int ans=0;
while(1)
{
int tmp=bfs();
if(tmp==-1)
return ans;
ans+=tmp;
int a=m;
int b;
while(a!=1)
{
b=pre[a];
residual[b][a]-=tmp;/* 正向流减小 */
residual[a][b]+=tmp;/* 反向流增加 */
a=b;
}
}
}
int main()
{
while(scanf("%d%d",&n,&m)==2)
{
input();
printf("%d\n",EK());
}
return 0;
}
...全文
142 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
HUANGFEIDIAN 2012-07-13
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 的回复:]

我是这样想的
首先将每个人做不同工作的收益做一个最大堆 堆里面每个元素包含如下信息,工作序号及做这项工作所得的收益 这个堆就根据收益来排序,这样我们就得到了n个最大堆,然后再根据每个堆的顶来构建一个结构体 这个结构体包含了 人的序号,工作的序号,做这项工作的收益,然后再根据收益对这n个结构体来排序建立一个最大堆 ,每次从这个最大堆里面提取最大的一个元素,输出这个元素,然后再根据元素的工作序号对……
[/Quote]
经手工验证是错的。。。。。
HUANGFEIDIAN 2012-07-13
  • 打赏
  • 举报
回复
我是这样想的
首先将每个人做不同工作的收益做一个最大堆 堆里面每个元素包含如下信息,工作序号及做这项工作所得的收益 这个堆就根据收益来排序,这样我们就得到了n个最大堆,然后再根据每个堆的顶来构建一个结构体 这个结构体包含了 人的序号,工作的序号,做这项工作的收益,然后再根据收益对这n个结构体来排序建立一个最大堆 ,每次从这个最大堆里面提取最大的一个元素,输出这个元素,然后再根据元素的工作序号对这个堆的剩余元素进行扫描,如果碰到工作序号相同的就对这个元素所代表的堆进行一次提取,但不输出,更新元素的值,然后再对这个元素下移到正确的位置,扫描完之后,再对这个堆进行提取,重复上述步骤,直到大堆中没有小堆为止
对每个小堆进行建堆 lg(n) 建堆所花时间n*lg(n)
建大堆花时间lg(n);
每次提取花时间lg(n),扫描花时间n/2(平均)如果碰到有序号相同的 则需要对小堆进行提取 花时间lg(n) 最多耗时n*lg(n)
n次提取耗时上限为n*(lg(n)+n/2+lg(n)*n)
所以总时间上线为lg(n)*(n+1)*(n+1) +n*n/2
不知道这个方法有没有效果
newtee 2012-07-13
  • 打赏
  • 举报
回复
急啊 没人鸟我啊 求高手啊
shaode01 2012-07-13
  • 打赏
  • 举报
回复
楼主心态不端正[Quote=引用 10 楼 的回复:]

难道csdn里面高手死了?
[/Quote]
newtee 2012-07-13
  • 打赏
  • 举报
回复
难道csdn里面高手死了?
newtee 2012-07-13
  • 打赏
  • 举报
回复
欢迎高手来解题 题目见5楼
newtee 2012-07-12
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 的回复:]
指派问题
问题描述:有n个人,计划做n项工作,其中 X(i,j)表示第i个人做第j项工作的收益,现求一种指派方式,使得每个人完成一项工作,并使总收益最大。
求C代码 最近在参加数学建模啊 没事搞搞算法
[/Quote]如题 等高手
newtee 2012-07-12
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 的回复:]
是在散分吗?
[/Quote]
才申请的号 没有分 4楼是真正目的
newtee 2012-07-12
  • 打赏
  • 举报
回复
指派问题
问题描述:有n个人,计划做n项工作,其中 表示第i个人做第j项工作的收益,现求一种指派方式,使得每个人完成一项工作,并使总收益最大。
求C代码 最近在参加数学建模啊 没事搞搞算法

chaoliu1024 2012-07-12
  • 打赏
  • 举报
回复
是在散分吗?
W170532934 2012-07-12
  • 打赏
  • 举报
回复
来拜读下的
newtee 2012-07-12
  • 打赏
  • 举报
回复
void *memset(void *s,int c,size_t n) 总的作用: 总的作用:将已开辟内存空间 s 的首 n 个字节的值设为值 c

69,371

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧