poj 1459 多源汇网络流 ISAP

来源:互联网 发布:一个顶级域名多少钱 编辑:程序博客网 时间:2024/06/08 02:22

题意:

给n个点,m条边,有np个源点,nc个汇点,求最大流

思路:

超级源点把所有源点连起来,边权是该源点的最大允许值;

所有汇点和超级汇点连接起来,边权是该汇点的最大允许值;

跑最大流

code:

#include<cstdio>#include<iostream>#include<cstring>#include<algorithm>#include<vector>#include<string>#include<queue>#include<map>#include<set>#include<cmath>#include<cstdlib>using namespace std;#define INF 0x3f3f3f3f#define PI acos(-1.0)#define mem(a, b) memset(a, b, sizeof(a))typedef pair<int,int> pii;typedef long long LL;//------------------------------const int maxn = 205;const int maxm = 205 * 205;const int max_nodes = maxn;struct Edge{      int from, to;      int capacity, flow;      Edge(){}      Edge(int from_, int to_, int capacity_, int flow_){            from = from_;            to = to_;            capacity = capacity_;            flow = flow_;      }};Edge edges[maxm];int cnte;vector<int> g[maxn];void graph_init(){      cnte = 0;      for(int i = 0; i < maxn; i++) g[i].clear();}void add_Edge(int from, int to, int cap){      edges[cnte].from = from;      edges[cnte].to = to;      edges[cnte].capacity = cap;      edges[cnte].flow = 0;      g[from].push_back(cnte);      cnte++;      edges[cnte].from = to;      edges[cnte].to = from;      edges[cnte].capacity = 0;      edges[cnte].flow = 0;      g[to].push_back(cnte);      cnte++;}int source;         // 源点int sink;           // 汇点int p[maxn];   // 可增广路上的上一条弧的编号int num[maxn]; // 和 t 的最短距离等于 i 的节点数量int cur[maxn]; // 当前弧下标int d[maxn];   // 残量网络中节点 i 到汇点 t 的最短距离bool visited[maxn];int num_nodes, num_edges;void bfs(){                   // 预处理, 反向 BFS 构造 d 数组      memset(visited, 0, sizeof(visited));      queue<int> q;      q.push(sink);      visited[sink] = true;      d[sink] = 0;      while(!q.empty()){            int u = q.front(); q.pop();            for(int i = 0; i < g[u].size(); i++){                  Edge& e = edges[g[u][i] ^ 1];                  int v = e.from;                  if(!visited[v] && e.capacity > e.flow){                        visited[v] = true;                        d[v] = d[u] + 1;                        q.push(v);                  }            }      }}int augment(){                                        // 增广      int u = sink, df = INF;      // 从汇点到源点通过 p 追踪增广路径, df 为一路上最小的残量      while(u != source){            Edge& e = edges[p[u]];            df = min(df, e.capacity - e.flow);            u = e.from;      }      u = sink;      // 从汇点到源点更新流量      while(u != source){            Edge& e = edges[p[u]];            e.flow += df;            edges[p[u]^1].flow -= df;            u = e.from;      }      return df;}int max_flow(){      int flow = 0;      bfs();      memset(num, 0, sizeof(num));      for(int i = 0; i < num_nodes; i++) num[d[i]] ++; // 这个地方,针对的是点从0开始编号的情况      int u = source;      memset(cur, 0, sizeof(cur));      while(d[source] < num_nodes){            if(u == sink){                  flow += augment();                  u = source;            }            bool advanced = false;            for(int i = cur[u]; i < g[u].size(); i++){                  Edge& e = edges[g[u][i]];                  if(e.capacity > e.flow && d[u] == d[e.to] + 1){                        advanced = true;                        p[e.to] = g[u][i];                        cur[u] = i;                        u = e.to;                        break;                  }            }            if(!advanced){    //retreat                  int m = num_nodes - 1;                  for(int i = 0; i < g[u].size(); i++){                        Edge& e = edges[g[u][i]];                        if(e.capacity > e.flow) m = min(m, d[e.to]);                  }                  if(--num[d[u]] == 0) break;                    // gap 优化                  num[d[u] = m+1] ++;                  cur[u] = 0;                  if(u != source){                        u = edges[p[u]].from;                  }            }      }      return flow;}//------------------------我是分界线,上面是模板--------------------------int np, nc, n, m;void solve(){      graph_init();      int u, v, w;      char ch;      for(int i = 1; i <= m; i++){            while(scanf("%c", &ch)){                  if(ch == '(') break;            }            scanf("%d,%d%c%d",&u,&v,&ch,&w);            add_Edge(u, v, w);      }      for(int i = 1; i <= np; i++){            while(scanf("%c", &ch)){                  if(ch == '(') break;            }            scanf("%d%c%d",&u, &ch, &w);            add_Edge(n, u, w);      }      for(int i = 1; i <= nc; i++){            while(scanf("%c", &ch)){                  if(ch == '(') break;            }            scanf("%d%c%d",&v, &ch, &w);            add_Edge(v, n+1, w);      }      num_nodes = n+2;      source = n; sink = n+1;      int ans = max_flow();      printf("%d\n",ans);}int main(){      while(scanf("%d%d%d%d",&n,&np, &nc, &m) != EOF){            solve();      }      return 0;}


终于自己写了一个还不错的最大流啦....窝原来用的那个模板我囧的很好了啊!但是我干囧大家好像都再说Dinic是好,又有人在说ISAP好像更棒啊!终于我现在两个都敲一下就好啦~~

ISAP跟DINIC还是有很多相似的。。


1 0