题目大意就不说了是一道裸的网络流中的最大流问题,可以用增广路算法来做,即EDMONDS-KARP算法。 读入会有多组数据,每一组先有N和M,N表示图中边的条数,M表示图中节点的个数,接下来有N行数据,每行有三个数 S ,E, C 表示一条边的起点,终点和边上的容量,注意是有向边,而且有重边;
好了题目就是这样,还是说一下这个算法吧,这个算法其实是很暴力的。。他每次只是用BFS找到一条路,使得在这条路上的每一条边的残流量(****即容量与流量(**流量就是实际使用的容量有正负的,如果从A到B 的流量是c,那么从B到A的流量就是-c因为方向相反嘛,是吧?**)之差******)都大于0(*******其中残流量就是经过使用后这条边上还剩余的可使用流量,是有向的,比如从v到u的容量是c,从u到v的容量是零,从v到u的流量是F,那么从u到v的流量就是-F,于是从v到u的残流量就是c-F,从u到v的残流量就是0-(-F)=F(************这个残流量实际是会变大的,是吧?因为本来不能把东西从U运到V的但是,你把东西从v运到u后,我就可以等效的认为可以把东西从u运到v了,为什么?想一想其实很简单,因为假设你想把5个东西从v往u运,而实际上你只运了2个,那我就可以这样说,你从v往u运了5个东西而我从u往v运了3个东西,这样结果是不是等价的????是吧,这就是残流量的神奇了***********)。 这些概念一定要龙清楚而且要知道怎么算*****)
啊,注释好像略多额,好吧继续说那个,找到了一条残流量都大于0的路径。这说明了什么呢?这条路?那就是这条路上可以运送东西?那可以运送多少东西呢?当然是这条路上的最小的残留量啊,是吧?想想其实很简单,如果不是最小的,那你把东西运到最小的残流量的那条边上的时候,他肯定就运不过去啊。
这样也知道运多少了,那就运呗,运的时候就更新一下整条路上的流量就行,注意正反的流量都需要更新。
然后就重复这个找路得过程就行了。直到找不到整条路的最小残流量都大于0路径,那么算法就结束了
/********* PRO: POJ 1273 TIT: Drainage Ditches DAT: 2013-08-12 AUT: UKean EMA: [email protected] ALG: Edmonds_Karp *********/ #include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<queue> #define INF 1e9 using namespace std; queue<int> que;//广搜需要使用的队列 int N,M;//N是边数,M是点数 int s,t;//源点和汇点 int flow[205][205];//流量 int p[205];//广搜记录路径的父节点数组 int a[205];//路径上的最小残流量 int cap[205][205];//容量网络 int ans; int read() { memset(cap,0,sizeof(cap)); for(int i=0;i<N;i++) { int sta,en,ca; cin>>sta>>en>>ca; cap[sta][en]+=ca;//这样就可以处理重边了 } s=1;t=M;//s是源点,t是汇点 return 1; } void deal()//最大流算法 { memset(flow,0,sizeof(flow));//初始化流量 ans=0;//最大流 while(1) { memset(a,0,sizeof(a)); a[s]=INF; que.push(s); while(!que.empty())//广搜找到增广路,就是那个最小的残流量大于零的路径 { int u=que.front();que.pop(); for(int v=1;v<=M;v++) if(!a[v]&&cap[u][v]-flow[u][v]>0)//cap[u][v]-flow[u][v] 表示残流量, //扩张新的的节点!a[v]确保该节点没被访问过,残流量大于0确保找的的路径符合要求 { p[v]=u;//用来记录v的父亲,保存路径 que.push(v);//入队 a[v]=min(a[u],cap[u][v]-flow[u][v]);//记录路径上的最小残流量 } } if(a[t]==0) break;//如果找不到路径最小残流量大于0的路径了就结束算法 for(int u=t;u!=s;u=p[u])//迭代找回路径修改,路径上的流量 { flow[p[u]][u]+=a[t];//更新正向的流量 flow[u][p[u]]-=a[t];//更新方向流量 } ans+=a[t];//增加最大流 } cout<<ans<<endl; } int main() { while(cin>>N>>M) { read(); deal(); } return 0; }