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
/*
ID: conicoc1
LANG: C
TASK: milk6
*/
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define INIFINITY 10000000
#define Min(a,b) a<b?a:b
int Temp[1001][2];
int Map[33][33];
int Dist[33];
int Flag[33];
int Vertex,Edges;
int Queue[33];
int Front=0,Rear=0;
int Ans1,Ans2[1001];
int Union[33];
int GAP[33];
int BuildDist()
{
memset(GAP,0,sizeof(GAP));
int V,i;
Queue[Rear++]=Vertex;
Dist[Vertex]=0;
Flag[Vertex]=1;
// GAP[0]=1;
while(Front!=Rear){
V=Queue[Front++];
for(i=1;i<=Vertex;i++){
if(Map[i][V]&&!Flag[i]){
Dist[i]=Dist[V]+1;
// GAP[Dist[i]]++;
Flag[i]=1;
Queue[Rear++]=i;
}
}
}
}
void SAP()
{
int i,Flow,V,Path[33];
V=1;
Ans1=0;
while(Dist[1]<Vertex){
if(V==Vertex){
Flow=INIFINITY;
while(V!=1){
Flow=Min(Flow,Map[Path[V]][V]);
V=Path[V];
}
V=Vertex;
while(V!=1){
Map[Path[V]][V]-=Flow;
Map[V][Path[V]]+=Flow;
V=Path[V];
}
Ans1+=Flow;
}
else{
for(i=1;i<=Vertex;i++){
if(Map[V][i]&&Dist[V]==Dist[i]+1){
Path[i]=V;
V=i;
break;
}
}
if(i==Vertex+1){
// GAP[Dist[V]]--;
// if(GAP[Dist[V]]==0)
// break;
Dist[V]=Vertex;
for(i=1;i<=Vertex;i++){
if(Map[V][i]&&Dist[i]!=-1)
Dist[V]=Min(Dist[V],Dist[i]+1);
}
// GAP[Dist[V]]++;
if(V!=1)
V=Path[V];
}
}
}
}
void FloodFill(int V)
{
int W;
Union[V]=Flag[V]=1;
for(W=1;W<=Vertex;W++)
if(Map[V][W]&&!Flag[W]){
FloodFill(W);
}
}
int main()
{
FILE *fin,*fout;
int i,j,V,W,Dis;
int TmpAns[1000];
fin=fopen("milk6.in","r");
fout=fopen("milk6.out","w");
memset(Map,0,sizeof(Map));
fscanf(fin,"%d %d",&Vertex,&Edges);
for(i=1;i<=Edges;i++){
fscanf(fin,"%d %d %d",&V,&W,&Dis);
Map[V][W]+=Dis;
Temp[i][0]=V;
Temp[i][1]=W;
}
memset(Dist,-1,sizeof(Dist));
BuildDist();
SAP();
Ans2[0]=(Ans1?INIFINITY:0);
for(i=1;i<=Vertex;i++){
memset(Flag,0,sizeof(Flag));
memset(Union,0,sizeof(Union));
memset(TmpAns,0,sizeof(TmpAns));
FloodFill(i);
if(Union[1]==Union[Vertex])
continue;
for(j=1;j<=Edges;j++)
if(Union[Temp[j][0]]&&Union[Temp[j][0]]!=Union[Temp[j][1]])
TmpAns[++TmpAns[0]]=j;
if(TmpAns[0]<Ans2[0]||(TmpAns[0]==Ans2[0]&&TmpAns[1]<Ans2[1])){
Ans2[0]=TmpAns[0];
for(j=1;j<=TmpAns[0];j++)
Ans2[j]=TmpAns[j];
}
}
fprintf(fout,"%d %d\n",Ans1,Ans2[0]);
for(i=1;i<=Ans2[0];i++){
fprintf(fout,"%d\n",Ans2[i]);
}
return 0;
}
最小割+残留网络的FloodFill胡搞一气。。。貌似还用了并查集?还不是为了找到边数最少的那组!
最大流用的SAP算法+GAP优化,话说一开始SAP求当前最大流的时候没有给最大流赋值为无穷。。结果各种超时悲剧
虽然是模板还是得自己多打打才能减少错误。。