• ZJOI 最小割 CQOI 不同的最小割 (最小割分治)


    题目1 ZJOI 最小割

    题目大意:

    求一个无向带权图两点间的最小割,询问小于等于c的点对有多少。

    算法讨论: 最小割 分治

    代码:

    #include <cstdlib>
    #include <iostream>
    #include <cstring>
    #include <algorithm>
    #include <cstdio>
    #include <vector>
     
    using namespace std;
    const int N = 150 + 5;
    const int M = 3000 + 5;
    const int oo = 0x3f3f3f3f;
    #define inf oo
     
    int n, m;
    bool mark[N];
    int a[N], tmp[N], ans[N][N];
     
    struct Edge {
      int from, to, cap, flow;
      Edge(int u = 0, int v = 0, int c = 0, int f = 0) :
        from(u), to(v), cap(c), flow(f) {}
    };
     
    struct Dinic {
      int n, mm, s, t;
      int dis[N], cur[N], que[N * 10];
      bool vis[N];
      vector <Edge> edges;
      vector <int> G[N];
     
      void clear() {
        for(int i = 0; i <= n; ++ i) G[i].clear();
        edges.clear();
      }
     
      void add(int from, int to, int cap) {
        edges.push_back(Edge(from, to, cap, 0));
        edges.push_back(Edge(to, from, cap, 0));
        mm = edges.size();
        G[from].push_back(mm - 2);
        G[to].push_back(mm - 1);
      }
     
      bool bfs() {
        int head = 1, tail = 1;
        memset(vis, false, (n + 1) * sizeof (bool));
        dis[s] = 0; vis[s] = true; que[head] = s;
        while(head <= tail) {
          int x = que[head];
          for(int i = 0; i < (signed) G[x].size(); ++ i) {
            Edge &e = edges[G[x][i]];
            if(!vis[e.to] && e.cap > e.flow) {
              vis[e.to] = true;
              dis[e.to] = dis[x] + 1;
              que[++ tail] = e.to;
            }
          }
          ++ head;
        }
        return vis[t];
      }
     
      int dfs(int x, int a) {
        if(x == t || a == 0) return a;
        int flw = 0, f;
        for(int &i = cur[x]; i < (signed) G[x].size(); ++ i) {
          Edge &e = edges[G[x][i]];
          if(dis[e.to] == dis[x] + 1 && (f = dfs(e.to, min(a, e.cap - e.flow))) > 0) {
            e.flow += f; edges[G[x][i] ^ 1].flow -= f; flw += f; a -= f;
            if(a == 0) break;
          }
        }
        return flw;
      }
     
      int maxflow(int s, int t) {
        this->s = s; this->t = t;
        int flw = 0;
        while(bfs()) {
          memset(cur, 0, sizeof cur);
          flw += dfs(s, oo);
        }
        return flw;
      }
     
      void rebuild() {
        for(int i = 0; i < (signed) edges.size(); ++ i)
          edges[i].flow = 0;
      }
     
      void dfs(int u) {
        mark[u] = true;
        for(int i = 0; i < (signed) G[u].size(); ++ i) {
          Edge e = edges[G[u][i]];
          if(!mark[e.to] && e.cap > e.flow) {
            dfs(e.to);
          } 
        }
      }
    }net;
     
    void Divide(int l, int r) {
      if(l >= r) return;
      net.rebuild();
      int nowflow = net.maxflow(a[l], a[r]);
      memset(mark, false, (n + 1) * sizeof (bool));
      net.dfs(a[l]);
      for(int i = 1; i <= n; ++ i)
        if(mark[i])
          for(int j = 1; j <= n; ++ j)
            if(!mark[j])
              ans[i][j] = min(ans[i][j], nowflow), ans[j][i] = ans[i][j];
      int L = l, R = r;
      for(int i = l; i <= r; ++ i)
        if(mark[a[i]]) tmp[L ++] = a[i];
        else tmp[R --] = a[i];
      for(int i = l; i <= r; ++ i) a[i] = tmp[i];
      Divide(l, L - 1); Divide(R + 1, r);//这不能二分一个Mid,因为S集和T集的大小不一定相同
    }
     
    int main() {
      int T, u, v, c, q;
      scanf("%d", &T);
      while(T --) {
        net.clear(); 
        scanf("%d%d", &n, &m); net.n = n;
        for(int i = 1; i <= n; ++ i) a[i] = i;
        for(int i = 1; i <= n; ++ i)
          for(int j = 1; j <= n; ++ j) ans[i][j] = inf;
        for(int i = 1; i <= m; ++ i) {
          scanf("%d%d%d", &u, &v, &c);
          net.add(u, v, c);
        }
        Divide(1, n);
        scanf("%d", &q);
        for(int i = 1; i <= q; ++ i) {
          int tmp = 0;
          scanf("%d", &c);
          for(int u = 1; u <= n; ++ u) {
            for(int v = u + 1; v <= n; ++ v) {
              if(ans[u][v] <= c) {
                ++ tmp;
              }
            }
          }
          printf("%d
    ", tmp);
        }
        puts("");
      }
      return 0;
    }
    

    题目2 CQOI2016 不同的最小割

    题目大意:

    求所有点对问不同的最小割数目。

    算法讨论: 最小割 分治

    和上面的一个题有区别么?

    代码:

    #include <cstdlib>
    #include <iostream>
    #include <cstring>
    #include <algorithm>
    #include <cstdio>
    #include <vector>
    #include <set>
     
    using namespace std;
    const int N = 850 + 5;
    const int M = 8500 + 5;
    const int oo = 0x3f3f3f3f;
     
    int n, m;
    int ans[N][N], tmp[N], a[N];
    bool mark[N];
    set <int> lts;
     
    struct Edge {
      int from, to, cap, flow;
      Edge(int u = 0, int v = 0, int cap = 0, int flow = 0):
        from(u), to(v), cap(cap), flow(flow) {}
    };
     
    struct Dinic {
      int n, m, s, t;
      int dis[N], cur[N], que[N * 10];
      bool vis[N];
      vector <Edge> edges;
      vector <int> G[N];
     
      void add(int from, int to, int cap) {
        edges.push_back(Edge(from, to, cap, 0));
        edges.push_back(Edge(to, from, cap, 0));
        m = edges.size();
        G[from].push_back(m - 2);
        G[to].push_back(m - 1);
      }
     
      bool bfs() {
        int head = 1, tail = 1;
        memset(vis, false, (n + 1) * sizeof (bool));
        dis[s] = 0; vis[s] = true; que[head] = s;
        while(head <= tail) {
          int x = que[head];
          for(int i = 0; i < (signed) G[x].size(); ++ i) {
            Edge &e = edges[G[x][i]];
            if(!vis[e.to] && e.cap > e.flow) {
              vis[e.to] = true;
              dis[e.to] = dis[x] + 1;
              que[++ tail] = e.to;
            }
          }
          ++ head;
        }
        return vis[t];
      }
     
      int dfs(int x, int a) {
        if(x == t || a == 0) return a;
        int flw = 0, f;
        for(int &i = cur[x]; i < (signed) G[x].size(); ++ i) {
          Edge &e = edges[G[x][i]];
          if(dis[e.to] == dis[x] + 1 && (f = dfs(e.to, min(a, e.cap - e.flow))) > 0) {
            e.flow += f; edges[G[x][i] ^ 1].flow -= f; a -= f; flw += f;
            if(a == 0) break;
          }
        }
        return flw;
      }
     
      int maxflow(int s, int t) {
        this->s = s; this->t = t;
        int flw = 0;
        while(bfs()) {
          memset(cur, 0, sizeof cur);
          flw += dfs(s, oo);
        }
        return flw;
      }
     
      void rebuild() {
        for(int i = 0; i < (signed) edges.size(); ++ i)
          edges[i].flow = 0;
      }
     
      void dfs(int u) {
        mark[u] = true;
        for(int i = 0; i < (signed) G[u].size(); ++ i) {
          Edge e = edges[G[u][i]];
          if(!mark[e.to] && e.cap > e.flow)
            dfs(e.to);
        }
      }
    }net;
     
    void Divide(int l, int r) {
      if(l >= r) return;
      net.rebuild();
      int nowflow = net.maxflow(a[l], a[r]);
      memset(mark, false, (n + 1) * sizeof(bool));
      net.dfs(a[l]);
      for(int i = 1; i <= n; ++ i)
        if(mark[i])
          for(int j = 1; j <= n; ++ j)
            if(!mark[j])
              ans[i][j] = min(ans[i][j], nowflow), ans[j][i] = ans[i][j];
      int L = l, R = r;
      for(int i = l; i <= r; ++ i)
        if(mark[a[i]]) tmp[L ++] = a[i];
        else tmp[R --] = a[i];
      for(int i = l; i <= r; ++ i)
        a[i] = tmp[i];
      Divide(l, L - 1); Divide(R + 1, r);
    }
     
    int main() {
      int u, v, c;
      scanf("%d%d", &n, &m);
      for(int i = 1; i <= m; ++ i) {
        scanf("%d%d%d", &u, &v, &c);
        net.add(u, v, c);
      }
      for(int i = 1; i <= n; ++ i) a[i] = i;
      for(int i = 1; i <= n; ++ i)
        for(int j = 1; j <= n; ++ j) ans[i][j] = oo;
      net.n = n;
      Divide(1, n);
      for(int i = 1; i <= n; ++ i) {
        for(int j = i + 1; j <= n; ++ j) {
          lts.insert(ans[i][j]);
        }
      }
      printf("%d
    ", lts.size());
      return 0;
    }
    
  • 相关阅读:
    调试与分析
    GCC
    汇编
    数据恢复
    TCP/IP
    shell
    vmstat、top
    计算程序运行时间的封装
    protobuf
    c++模板
  • 原文地址:https://www.cnblogs.com/sxprovence/p/5320043.html
Copyright © 2020-2023  润新知