Description
你第一天接手三鹿牛奶公司就发生了一件倒霉的事情:公司不小心发送了一批有三聚氰胺的牛奶。很不幸,你发现这件事的时候,有三聚氰胺的牛奶已经进入了送货网。这个送货网很大,而且关系复杂。你知道这批牛奶要发给哪个零售商,但是要把这批牛奶送到他手中有许多种途径。送货网由一些仓库和运输卡车组成,每辆卡车都在各自固定的两个仓库之间单向运输牛奶。在追查这些有三聚氰胺的牛奶的时候,有必要保证它不被送到零售商手里,所以必须使某些运输卡车停止运输,但是停止每辆卡车都会有一定的经济损失。你的任务是,在保证坏牛奶不送到零售商的前提下,制定出停止卡车运输的方案,使损失最小。
{批注:先前不知是哪个写了一个要不得的翻译,这才是正常的翻译,读起来也觉得比较健康——Cow-Tsc} {修改下,更现实——pyh119}
Input
(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
(file milk6.out) 第1行两个整数c、t,c表示最小的损失,T表示要停止的最少卡车数。接下来t 行表示你要停止哪几条线路。如果有多种方案使损失最小,输出停止的线路最少的方案。如果仍然还有相同的方案,请选择开始输入顺序最小的。
Analysis
本来想用邻接表的但是不好打啊毕竟关系到删边什么的
首先要知道最大流=最小割(证明略)
先跑一次最大流,然后枚举删掉一条边分别跑m次最大流,如果此时最大流+删去的边的边权=原本最大流,那么可以肯定这条边在最小割集合中
在做之前要按边权降序排序,这样可以删掉最少的边
Code
/*
ID:wjp13241
PROG:milk6
LANG:C++
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <algorithm>
#define fo(i,a,b) for (int i=a;i<=b;i++)
#define fil(x,t) memset(x,t,sizeof(x))
#define STP system("pause")
#define min(x,y) x<y?x:y
#define max(x,y) x>y?x:y
#define INF 0x7f7f7f7f
#define E 1021*2+1
#define N 33
using namespace std;
struct edge{int x,y,w,id;}e[E];
int c[N][N],bac[N][N],vis[N],p[E],cnt=0;
int add(int x,int y,int w){c[x][y]+=w;bac[x][y]+=w;e[++cnt]=(edge){x,y,w,cnt};}
int cmp(edge x,edge y){return x.w>y.w||x.w==y.w&&x.id<y.id;}
int rec(int n)
{
fo(i,1,n)
fo(j,1,n)
c[i][j]=bac[i][j];
}
int find(int x,int n,int mn)
{
vis[x]=1;
if (x==n)
return mn;
fo(i,1,n)
if (c[x][i]>0&&!vis[i])
{
int d=find(i,n,min(mn,c[x][i]));
if (d!=0)
{
c[x][i]-=d;
c[i][x]+=d;
return d;
}
}
return 0;
}
int main()
{
freopen("milk6.in","r",stdin);
freopen("milk6.out","w",stdout);
ios::sync_with_stdio(false);
int n,m;
cin>>n>>m;
fil(c,0);
fo(i,1,m)
{
int x,y,w;
cin>>x>>y>>w;
add(x,y,w);
}
rec(n);
sort(e+1,e+cnt+1,cmp);
int mxFlow=0;
fil(vis,0);
while (int tmp=find(1,n,INF))
{
fil(vis,0);
mxFlow+=tmp;
}
cout<<mxFlow<<" ";
int ans=0;
fo(i,1,cnt)
{
rec(n);
c[e[i].x][e[i].y]-=e[i].w;
int tot=0;
fil(vis,0);
while (int tmp=find(1,n,INF))
{
fil(vis,0);
tot+=tmp;
}
if (tot+e[i].w==mxFlow)
{
ans++;
p[e[i].id]=1;
mxFlow-=e[i].w;
bac[e[i].x][e[i].y]-=e[i].w;
}
}
cout<<ans<<endl;
fo(i,1,m)
if (p[i])
cout<<i<<endl;
return 0;
}