usaco training 4.4.2 Pollutant Control 追查坏牛奶 题解

Pollutant Control题解
Hal Burch

It's your first day in Quality Control at Merry Milk Makers, and already there's been a catastrophe: a shipment of bad milk has been sent out. Unfortunately, you didn't discover this until the milk was already into your delivery system on its way to stores. You know which grocer that milk was destined for, but there may be multiple ways for the milk to get to that store.

The delivery system is made up of a several warehouses, with trucks running from warehouse to warehouse moving milk. While the milk will be found quickly, it is important that it does not make it to the grocer, so you must shut down enough trucks to ensure that it is impossible for the milk to get to the grocer in question. Every route costs a certain amount to shut down. Find the minimum amount that must be spent to ensure the milk does not reach its destination, along with a set of trucks to shut down that achieves this goal at that cost.

PROGRAM NAME: milk6

INPUT FORMAT

Line 1:Two space separated integers, N and M. N (2 <= N <= 32) is the number of warehouses that Merry Milk Makers has, and M (0 <= M <= 1000) is the number of trucks routes run. Warehouse 1 is actually the productional facility, while warehouse N is the grocer to which which the bad milk was destined.
Line 2..M+1:Truck routes: three space-separated integers, Si, Ei, and Ci. Si and Ei (1 <= Si,Ei <= N) correspond to the pickup warehouse and dropoff warehouse for the truck route. Ci (0 <= Ci <= 2,000,000) is the cost of shutting down the truck route.

SAMPLE INPUT (file milk6.in)

4 5
1 3 100
3 2 50
2 4 60
1 2 40
2 3 80

OUTPUT FORMAT

The first line of the output should be two integers, C and T. C is the minimum amount which must be spent in order to ensure the our milk never reaches its destination. T is the minimum number of truck routes that you plan to shut down in order to achive this goal. The next T lines sould contain a sorted list of the indexes of the truck routes that you suggest shutting down. If there are multiple sets of truck routes that achieve the goal at minimum cost, choose one that shuts down the minimum number of routes. If there are still multiple sets, choose the one whose initial routes have the smallest index.

SAMPLE OUTPUT (file milk6.out)

60 1
3

描述

你第一天接手三鹿牛奶公司就发生了一件倒霉的事情:公司不小心发送了一批有三聚氰胺的牛奶。很不幸,你发现这件事的时候,有三聚氰胺的牛奶已经进入了送货网。这个送货网很大,而且关系复杂。你知道这批牛奶要发给哪个零售商,但是要把这批牛奶送到他手中有许多种途径。送货网由一些仓库和运输卡车组成,每辆卡车都在各自固定的两个仓库之间单向运输牛奶。在追查这些有三聚氰胺的牛奶的时候,有必要保证它不被送到零售商手里,所以必须使某些运输卡车停止运输,但是停止每辆卡车都会有一定的经济损失。你的任务是,在保证有三聚氰胺的牛奶不送到零售商的前提下,制定出停止卡车运输的方案,使损失最小。

[编辑]格式

PROGRAM NAME: milk6

INPUT FORMAT:

(file milk6.in) 第一行: 两个整数N(2<=N<=32)、M(0<=M<=1000), N表示仓库的数目,M表示运输卡车的数量。仓库1代 表发货工厂,仓库N代表有三聚氰胺的牛奶要发往的零售商。 第2..M+1行: 每行3个整数Si,Ei,Ci。其中Si,Ei表示这 辆卡车的出发仓库,目的仓库。Ci(0 <= C i <= 2,000,000) 表示让这辆卡车停止运输的损失。


OUTPUT FORMAT:

(file milk6.out) 第1行两个整数C,T。C表示最小的损失,T表示要停止的最少卡车数。接下来T行表示你要停止哪几条线路。如果有多种方案使损失最小,输出停止的线路最少的方案。如果仍然还有相同的方案,请选择开始输入顺序最小的。

[编辑]SAMPLE INPUT

4 5
1 3 100
3 2 50
2 4 60
1 2 40
2 3 80 

[编辑]SAMPLE OUTPUT

60 1
3


        这题一看就是最小割的网络流,于是乎转化为最大流。但是麻烦的是,同时还要处理最小的边数以及字典序最小的输出。这可怎么办啊?网上的各种办法都是把边权*1001+1等等。但是我仍然就得这种方法有待商榷。

        询问了威武的SYF,得到了正解。我们先求出最小割,然后把边权从大到小排序。(这样的话,割的边数会更少)每次枚举一条边,模拟删掉这条边并再求最小割。如果最小割减少的量等于这条边的边权,说明这条边在最小割的集合里。然后真的删除这条边,继续处理。最后输出删除的边数即可。

        最后提醒一下:从x到y可以有很多条不同的路,所以在删边时不能直接赋成0,而是减掉这条边的边权。

代码:

/*
PROG:milk6
ID:juan1973
LANG:C++
*/
#include<stdio.h>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int e=1005;const int v=40;
struct arr{int l,r,s,num;}a[e];
bool flag[v];
int map[v][v],f[v][v],x[v],pre[v],write[e];
int n,m,i,ans,temp,cnt,xx,y,z;
bool cmp(arr a,arr b) {return a.s>b.s||a.s==b.s&&a.num<b.num;}
bool cmp2(int a,int b) {return a<b;}
int flow(int k)
{
  int pop=0,i,j;
  for (i=1;i<=n;i++)
    for (j=1;j<=n;j++)
      map[i][j]=f[i][j];
  map[a[k].l][a[k].r]-=a[k].s;
  while (true)
  {
    int h=0,t=1;x[1]=1;
    memset(pre,-1,sizeof(pre));
    while (h<t)
    {
      int now=x[++h];
      for (i=1;i<=n;i++)
        if (pre[i]<0&&map[now][i]>0)
        {
          pre[i]=now;x[++t]=i;
        }
      if (pre[n]>0) break;
    }
    if (pre[n]<0) break;int aug=2100000000;
    for (i=n;i!=1;i=pre[i]) aug=min(aug,map[pre[i]][i]);
    pop+=aug;
    for (i=n;i!=1;i=pre[i])
    {
      map[pre[i]][i]-=aug;map[i][pre[i]]+=aug;
    }
  }
  return pop;
}
int main()
{
  freopen("milk6.in","r",stdin);
  freopen("milk6.out","w",stdout);
  scanf("%ld%ld",&n,&m);
  for (i=1;i<=m;i++)
  {
    scanf("%ld%ld%ld",&xx,&y,&z);
    f[xx][y]+=z;
    a[i].s=z;a[i].num=i;
    a[i].l=xx;a[i].r=y;
  }
  ans=flow(0);printf("%ld ",ans);
  sort(a+1,a+m+1,cmp);
  for (i=1;i<=m;i++)
  {
    temp=flow(i);
    if (a[i].s+temp==ans)
    {
      f[a[i].l][a[i].r]-=a[i].s;
      write[++cnt]=a[i].num;
      ans=temp;
    }  
  }
  printf("%ld\n",cnt);
  sort(write+1,write+cnt+1,cmp2);
  for (i=1;i<=cnt;i++)
    printf("%ld\n",write[i]);
}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
USACO2022金组是国际在线判题系统USACO的最高级别,题目难度较高,在该比赛中取得好成绩是一项巨大的成就。以下是对该比赛的一些题目解析。 第一题:“交通计划” 题目要求:给定一个n个节点的有向图,每条边有一个长度,希望添加最少的边使得所有节点连通,求最小生成树的权值和。 解析:该题可以使用Kruskal算法求解,将每条边按权值从小到大排序,再依次加入,判断加入的边是否会形成环,若形成则不加入,直到所有节点连通为止。此时Kruskal算法得到的最小生成树的权值和即为所求。 第二题:“点火计划” 题目要求:给定一个n个节点的有向图,每条边有一个权值和一个点火时长,每个节点有一个点火启动时刻和时刻结束时刻,希望从其中选出一些边点火,使得所有节点都可从点火的边出发到达,且所选点火边的总点火时长最小。 解析:该题可以使用最小费用最大算法求解。将每条边看做一个容量为1,费用为点火时长的边,源点向节点的点火边容量为1,费用为0的边,节点的点火边向汇点的容量为1,费用为0的边,对这个网络进行最小费用最大即可得到所选边的总点火时长最小。 第三题:“美味佳肴” 题目要求:给定n个菜品,每个菜品有它的权值和两个类别,希望选出k个菜品,使得选出的菜品数量在每个类别中都不超过$\frac{k}{3}$个,且所选菜品的权值和最大。 解析:该题可以使用动态规划求解。设$f[i][j][k]$表示前i个菜品中,选择j个一类菜品,选择k个二类菜品的最大权值和,状态转移方程为$f[i][j][k]=max(f[i-1][j][k],f[i-1][j-1][k]+a[i],f[i-1][j][k-1]+b[i])$,其中a[i]为i号菜品的权值,若为一类则为该权值,否则为0,b[i]为i号菜品的权值,若为二类则为该权值,否则为0。最终答案为$f[n][$k/3$][$k/3$]。 以上是对USACO2022金组的部分题目的解析,USACO比赛是全球范围内的计算机竞赛,竞争非常激烈,能够在该比赛中脱颖而出是一项非常棒的成就。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值