【USACO4.4.2】追查坏牛奶(BSOI2140)

【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) 表示让这辆卡车停 止运输的损失

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




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值