坑人的网络流~~自己看了好几遍,又模拟了好几遍终于写出了这道最基本的网络流,这也算是网络流入门了吧~~~
自己理解的网络流:
网络流:1.现将sum=0赋初值;
2.首先使用的是bfs或dfs找出一条到达终点的路径。记录它的权重的最小值;(用BFS时路径需要用到队列来存储)。
3.sum加上每条路径上权重的最小值;
4.将顺序路径相减,将逆序路径相加得到正确结果;
反复调用(2)(3)和(4),得出正确结果。
下面 用poj上的 http://poj.org/problem?id=1273 Drainage Ditches这道题来进行讲解;
算法分析:
1:注意如果一条道上有多条排水沟,则多条排水沟的流量相加:
2:用BFS和DFS的方法来寻找最短路径;并记录下来这条路径下的最小流量;
3:将顺序路径相减,将逆序路径相加~得出正确的结果:
连续调用直到不存在从原点到终点的最短路径为止;
post code:
#include<stdio.h> #include<iostream> #include<string.h> #include<queue> using namespace std; int n,point,network[210][210],pre[210],flow[210]; queue<int> myqueue; int getmin(int a,int b ) { if(a<b)return a; else return b; } int Bfs() { bool used[210]; int nowpoint,i; flow[1]=2000000000; for(i=2;i<205;i++) flow[i]=-1; memset(used,0,sizeof(used)); memset(pre,0,sizeof(pre)); while(myqueue.empty()==0) myqueue.pop(); myqueue.push(1); while(myqueue.empty()==0) { nowpoint=myqueue.front(); myqueue.pop(); for(i=1;i<=point;i++) { if(used[i]==0&&network[nowpoint][i]>0) { used[i]=1; pre[i]=nowpoint; flow[i]=getmin(flow[nowpoint],network[nowpoint][i]); myqueue.push(i); } } } if(flow[point]==-1)return 0; else return flow[point]; } int Edmonds_karp() { int now,prea,ans=0,result,i; while(result=Bfs()) { max++; ans+=result; now=point; while(now!=1) { prea=pre[now]; network[prea][now]-=result; network[now][prea]+=result; now=prea; } } return ans; } int main() { while( scanf("%d %d",&n,&point)!=EOF ) { memset(network,0,sizeof(network)); memset(pre,0,sizeof(pre)); int i,x,y,z; for(i=1;i<=n;i++) { scanf("%d %d %d",&x,&y,&z); network[x][y]+=z ; } printf("%d\n",Edmonds_karp()); } }
注意要采用 队列的库函数 这样更方便:下面是自己才用的队列的库函数:
#include<iostream> #include<stdio.h> #include<queue> using namespace std; int main() { queue<int> myqueue; int i,m,say; scanf("%d %d",&i,&m); myqueue.push(i); myqueue.push(m); say=myqueue.front(); myqueue.pop(); printf("%d\n",say); say=myqueue.front(); myqueue.pop(); printf("%d\n",say); }