【USACO4.2.1】草地排水 最大流

来源:互联网 发布:小鸭淘宝复制软件 编辑:程序博客网 时间:2024/04/28 17:21

直接套用ISAP模板


我的模板不一定正确…… 不能参考!!!!!



/*TASK:ditchLANG:C++*/#include <iostream>#include <queue>#include <cstdio>#include <cstring>#include <cstdlib>using namespace std;const int max_ver = 200 + 10;int n, m;struct edge{int ver, cap, flow;edge *next, *rev;edge(){}edge(int _Ver, int _Cap, edge* _Next):ver(_Ver), cap(_Cap), next(_Next), flow(0), rev(NULL){}}*net[max_ver]={NULL};inline void insert_edge(int s, int t, int cap){net[s] = new edge(t, cap, net[s]);net[t] = new edge(s, 0, net[t]);net[s] -> rev = net[t];net[t] -> rev = net[s];}void init(){scanf("%d%d", &m, &n);while (m--){int a, b , c;scanf("%d%d%d", &a, &b, &c);insert_edge(a, b, c);}}queue<int>q;int dist[max_ver], numbs[max_ver];void rev_bfs(int s = 1, int t = n){q.push(t);for (int i = 1; i <= n; ++ i)dist[i] = 0x7fffffff;memset(numbs, 0, sizeof(numbs));numbs[0] = 1;q.push(t);dist[t] = 0;while (!q.empty()){int now = q.front();q.pop();for (edge *e = net[now]; e; e = e -> next){int will = e -> ver;if (dist[will] != 0x7fffffff || e -> rev -> cap == 0)continue;dist[will] = dist[now] + 1;++ numbs[dist[will]];q.push(will);}}}edge *CurEdge[max_ver], *revpath[max_ver];int totflow(0);void augflow(int s = 1, int t = n){int augflow = 0x7fffffff;for (int i = s; i != t; i = CurEdge[i] -> ver){//cout<<"["<<i<<"]"<<endl;augflow = min(augflow, CurEdge[i] -> cap);}for (int i = s; i != t; i = CurEdge[i] -> ver){CurEdge[i] -> cap -= augflow;CurEdge[i] -> rev -> cap += augflow;CurEdge[i] -> flow += augflow;CurEdge[i] -> rev -> flow -= augflow;}totflow += augflow;}void maxflow(int s = 1, int t = n){int totalflow = 0;for (int i = 1; i <= n; ++ i)CurEdge[i] = net[i];//当前弧优化!int now = s;while (dist[s] < n) // 起点到终点的距离比n小。一旦到n,肯定是到不了。 比如1->2 如果1->2距离是2,肯定是不可能的{if (now == t){augflow();now = s;}edge *e;for (e = CurEdge[now]; e; e = e -> next)if (e -> cap > 0 && dist[now] == dist[e -> ver] + 1)break;//找到一个可行的路if (e){CurEdge[now] = e;revpath[e -> ver] = e -> rev; //计算will是从哪里来的,为了回溯now = e -> ver;}else{ //失败了,显然要回溯if (0 == (--numbs[dist[now]]))break; //如果一个距离已经没有了。 出现断层了 显然就应该结束了CurEdge[now] = net[now];int mindist = n;for (edge *te = net[now]; te; te = te -> next)if (te -> cap >0)mindist = min(mindist, dist[te -> ver]);dist[now] = mindist + 1;++ numbs[dist[now]];if (now != s)now = revpath[now] -> ver;}}printf("%d\n", totflow);}int main(){freopen("ditch.in","r",stdin);freopen("ditch.out","w",stdout);init();rev_bfs(1, n);maxflow(1, n);return 0;}


0 0
原创粉丝点击