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\n",i,dep[i]);
  if(dep[t]) return 1;
  else return 0;
}
int find(int u,int f)//在u点,要解决值为f的流量
{
  //printf("%d %d\n",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);
}
      

 

posted on 2018-12-20 19:18  L_M_A  阅读(79)  评论(0编辑  收藏  举报

导航