zoukankan      html  css  js  c++  java
  • USACO 4.4 追查坏牛奶

    好题呀quq

    第一问根据最大流最小割定理,求出最大流就是最小割的值

    第二问就十分麻烦了,USACO还有一个加强版:求割边的割集,这就比较棘手了

    有一个比较投机取巧的方法:将所有的边权乘以一个大质数并加一,此时的答案ans与原来的答案pre相比,有如下关系

    ans = temp * mod + k

    k即为最小割的边数

    但这样的方法是过不去USACO的,我们得从最大流的本质去考虑

    考虑到:对于一个割C(S,T),所有从S到T的边必然满流(否则残余网络上还有增广路,可以继续更新最大流)所以满流的边**可能**成为割边,但不一定全都是(反例参照题目样例) 但是,如果一条边是割边,割掉这条边后,原图的流量一定减去它的流量(如果不是这样的话,说明可以用其他的边代替这个边,此边就没有必要割了)

    所以,我们选出图中所有满流边,每次试着去割去一条,看其是否是割边(依照上文的方法)即可

    这里给出第一种方法的代码,第二种方法调好后我会马上上发

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<iostream>
    #include<queue>
    #include<vector>
    using namespace std;
    #define int long long 
    const int maxn = 10005;
    const int maxm = 2e5 + 5;
    const int inf = 999999999;
    const int mod = 1007;
    inline int read()
    {
      int ans = 0,op = 1;
      char ch = getchar();
      while(ch < '0' || ch > '9')
        {
          if(ch == '-') op = -1;
          ch = getchar();
        }
      while(ch >= '0' && ch <= '9')
        {
          (ans *= 10) += ch - '0';
          ch = getchar();
        }
      return ans * op;
    }
    struct egde
    {
      int to,cost,next,other;
    }e[maxm];
    int fir[maxn],alloc;
    void adde(int u,int v,int w)
    {
      e[++alloc].next = fir[u];
      fir[u] = alloc;
      e[alloc].to = v;
      e[alloc].cost = w * mod + 1;
      e[alloc].other = alloc + 1;
      swap(u,v);
      e[++alloc].next = fir[u];
      fir[u] = alloc;
      e[alloc].to = v;
      e[alloc].cost = 0;
      e[alloc].other = alloc - 1;
    }
    int n,m,s,t;
    int cnt,ans;
    bool vis[maxn];
    int dep[maxn];
    bool bfs(int s,int t)
    {
      memset(dep,0,sizeof(dep));
      queue<int> q;
      dep[s] = 1;
      q.push(s);
      while(q.size())
        {
          int u = q.front();
          q.pop();
          for(int i = fir[u];i;i = e[i].next)
        {
          int v = e[i].to,c = e[i].cost;
          if(c > 0 && dep[v] == 0 && vis[i] == 0)
            {
              dep[v] = dep[u] + 1;
              q.push(v);
            }
        }
        }
      //for(int i = 1;i <= n;i++) printf("%d %d
    ",i,dep[i]);
      if(dep[t]) return 1;
      else return 0;
    }
    int find(int u,int f)//在u点,要解决值为f的流量
    {
      //printf("%d %d
    ",u,f);
      if(u == t) return f;
      int curflow = 0,t = 0;
      for(int i = fir[u];i;i = e[i].next)
        {
          int v = e[i].to,c = e[i].cost;
          if(c > 0 && dep[v] == dep[u] + 1 && curflow < f && vis[i] == 0)
        {
          t = find(v,min(c,f - curflow));
          curflow += t;
          e[i].cost -= t;
          e[e[i].other].cost += t;
        }
        }
      return curflow;
    }
    main()
    {
      n = read(),m = read();
      for(int i = 1;i <= m;i++)
        {
          int u = read(),v = read(),w = read();
          adde(u,v,w);
        }
      s = 1,t = n;
      while(bfs(s,t))
        ans += find(s,inf);
      printf("%d ",ans / mod);
      printf("%d",ans % mod);
    }
          
  • 相关阅读:
    缓冲流
    properties类
    io流
    异常处理
    file的概述和作用
    map集合和set集合
    js 判断是否是undefined null NaN
    java instanceof 判断是否是String
    ajax获取数据中文乱码问题最简单的完美解决方案
    if else if else if else 的用法
  • 原文地址:https://www.cnblogs.com/LM-LBG/p/10151683.html
Copyright © 2011-2022 走看看