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]);
}