【USACO4.4.2】追查坏牛奶
Description
你第一天接手光明牛奶公司就发生了一件倒霉的事情:公司不小心发送了一批坏牛奶。很不幸,你发现这件事的时候,坏牛奶已经进入了送货网。这个送货网很大,而且关系复杂。你知道这批牛奶要发给哪个零售商,但是要把这批牛奶送到他手中有许多种途径。送货网由一些仓库和运输卡车组成,每辆卡车都在各自固定的两个仓库之间单向运输牛奶。在追查这些坏牛奶的时候,有必要保证它不被送到零售商手里,所以必须使某些运输卡车停止运输,但是停止每辆卡车都会有一定的经济损失。你的任务是,再保证坏牛奶不送到零售商的前提下,制定出停止卡车运输的方案,使损失最小。
Input
第一行: 两个整数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) 表示让这辆卡车停 止运输的损失
第2..M+1行: 每行3个整数 Si, Ei, Ci. Si ,Ei表示这 辆卡车的出发仓库,目的仓库。Ci(0 <= C i <= 2,000,000) 表示让这辆卡车停 止运输的损失
Output
第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
Solution
给定一个有向图,求割边数最小的最小割集,并按照字典序输出。 根据数据加边,并且将边按照容量的大小排序。按照边的大小顺序并通过枚举的方式得出最小割集,并且将其进行sort排序后输出。具体方式详见
【Baltic2008】黑手党(Mafia)(BSOI2891) http://blog.csdn.net/hwzzyr/article/details/56012697
CODE
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
struct Pipe{int next,to,flow,f;}pipe[10005];
Pipe tg[10005],ttg[10005];
int h[55],cnt=1;
inline void add(int x,int y,int z){
pipe[++cnt].to=y;pipe[cnt].next=h[x];h[x]=cnt;pipe[cnt].flow=z;pipe[cnt].f=1;
pipe[++cnt].to=x;pipe[cnt].next=h[y];h[y]=cnt;pipe[cnt].flow=0;pipe[cnt].f=1;
return ;
}
inline int read(){
char c;int rec=0;
while((c=getchar())<'0'||c>'9');
while(c>='0'&&c<='9')rec=rec*10+c-'0',c=getchar();
return rec;
}
struct node{int val,id;}ppp[10005];
inline bool cmp(node x,node y){return x.val>y.val||x.val==y.val&&x.id<y.id;}//分别按照两个关键字排序
int Gap[55],dis[55];
long long ans,sum;
long long tot;
long long a[55];
int N,M;
inline int SAP(int v,int maxflow){
if(v==N)return maxflow;
int temp=maxflow,i,j,p;
for(i=h[v];i;i=pipe[i].next){
if(pipe[i].f==0)continue;
j=pipe[i].to;
if(pipe[i].flow&&dis[v]==dis[j]+1){
p=SAP(j,min(pipe[i].flow,temp));
temp-=p;pipe[i].flow-=p;pipe[i^1].flow+=p;
if(temp==0||dis[1]==N)return maxflow-temp;
}
}
if(--Gap[dis[v]]==0)dis[1]=N;
else Gap[++dis[v]]++;
return maxflow-temp;
}
inline void Get(){
memset(Gap,0,sizeof(Gap));
memset(dis,0,sizeof(dis));
Gap[0]=N;sum=0;
while(dis[1]<N)sum+=SAP(1,0x3f3f3f3f);
return ;
}
inline void Solve(){
ans=sum;
cout<<ans<<" ";
int i,j,p;
for(p=1;p<=M;p++){
if(ans==0)break;
i=ppp[p].id;
if(pipe[i*2].f){
for(j=1;j<=cnt;j++)tg[j]=pipe[j];
for(j=1;j<=cnt;j++)pipe[j]=ttg[j];
pipe[i*2].f=pipe[i*2+1].f=0;
Get();
if(ans-sum==ttg[i*2].flow){
a[++a[0]]=i;
ttg[i*2].f=ttg[i*2+1].f=0;
ans=sum;
}
else for(j=1;j<=cnt;j++)pipe[j]=tg[j];
}
}
return ;
}//枚举断边
int main(){
N=read();M=read();
int i,x,y,z;
for(i=1;i<=M;i++){
x=read();y=read();z=read();
add(x,y,z);
ppp[i].id=i;ppp[i].val=z;
}
for(i=1;i<=cnt;i++)ttg[i]=pipe[i];
sort(ppp+1,ppp+1+cnt,cmp);
Get();
Solve();
cout<<a[0]<<endl;
sort(a+1,a+1+a[0]);
for(i=1;i<=a[0];i++)cout<<a[i]<<'\n';//每一个值换一行(相当坑)
return 0;
}