一、一句话描述网络流问题
有向图,有多重边,每条边上有容量限制。指定起点和终点,求从起点到终点的最大容量。
二、一句话描述基本网络算法
残量网络:考虑有向边,如果通过了正向流量,则消耗正向容量。同时增加反向流量。
增广路径:考虑有向图,如果能够找到一条路,在当前流量状态下,能够从开始走到结束,且路径经过的最小容量大于零,则认为可以选择这条路径作为答案。
最大流:每次找到“增广路径”,都将答案更新至残量网络中。直到某一次在完成搜索之后没能找到一条增广路径。
三、一句话描述遇到的坑
最开始看到增广路径概念之后把网络流当成了无向图模型。
四、一个列表表示网络流基础算法可以过得题
http://hihocoder.com/problemset/problem/1369
http://acm.hdu.edu.cn/showproblem.php?pid=3549
http://poj.org/problem?id=1273
五、差不多通用的代码:
#include<iostream> #include<stdio.h> #include<string> #include<vector> #include<queue> #include<string.h> #include<math.h> using namespace std; #define ll long long #define pp pair<ll,ll> #define vecp vector<pp> #define veci vector<int> const ll MAXN=500+233; const ll INF = 50000000+23333; class edge { public : ll a,b,c; edge(ll a,ll b,ll c) { this->a=a; this->b=b; this->c=c; } edge(){} }; veci G[MAXN]; vector<edge> path; ll vis[MAXN]; ll n,m; void add_edge(ll a,ll b,ll c) { // path.push_back(make) path.push_back(edge(a,b,c)); G[a].push_back(path.size()-1); path.push_back(edge(b,a,0)); G[b].push_back(path.size()-1); } ll dfs(ll now,ll minn) { if(vis[now]||minn <= 0 )return 0; vis[now]=1; if(now == n)return minn; ll len = G[now].size(); for(ll i=0;i<len;++i) { ll pos = G[now][i]; ll tar = path[pos].b; ll mm = min(path[pos].c,minn); ll res = dfs(tar,mm); if(res) { path[pos].c -= res; path[pos^1].c += res; return res; } }return 0; } ll cases=0; void init() { cases++; for(ll i=0;i<=n;++i)G[i].clear(); path.clear(); memset(vis,0,sizeof(vis)); for(ll i=0;i<m;++i) { ll a,b,c; cin>>a>>b>>c; add_edge(a,b,c); } ll res = dfs(1,INF); ll ans = res; while(res) { memset(vis,0,sizeof(vis)); res = dfs(1,INF); ans += res; } cout<<ans<<endl; // prllf("Case %d: %d ",cases,ans); } int main() { cin.sync_with_stdio(false); ll t=1 ; while(cin>>m>>n)init(); // cin>>t; // for(ll i=0;i<t;++i) // { // cin>>m>>n; // init(); // } // while(cin>>n>>m)init(); return 0; }