P1344 [USACO4.4] 追查坏牛奶 Pollutant Control

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排序后输出。具体方式详见

见代码:

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
using namespace std;
typedef long long ll;
const int inf=99999999;
struct node
{
	int x,y,c,next,other,ds;
}a[2100],d[2100];int len,last[2100];
void ins(int x,int y,int c)
{
	len++;int k1=len;
	a[len].x=x;a[len].y=y;a[len].c=c;
	a[len].next=last[x];last[x]=len;
	len++;int k2=len;
	a[len].x=y;a[len].y=x;a[len].c=0;
	a[len].next=last[y];last[y]=len;
	a[k1].other=k2;
	a[k2].other=k1;
}
int list[2100],head,tail,h[2100];
int st,ed,b[2100],lenb;
bool bfs()
{
	memset(h,0,sizeof(h));h[st]=1;
	list[1]=st;head=1;tail=2;
	while(head<tail)
	{
		int x=list[head];
		for(int k=last[x];k;k=a[k].next)
		{
			int y=a[k].y;
			if(h[y]==0&&a[k].c>0)
			{
				h[y]=h[x]+1;
				list[tail]=y;
				tail++;
			}
		}
		head++;
	}
	if(h[ed]==0)return false;
	else return true;
}
int findflow(int x,int f)
{
	if(x==ed)return f;
	int s=0;
	for(int k=last[x];k;k=a[k].next)
	{
		int y=a[k].y;
		if(h[y]==h[x]+1&&a[k].c>0&&s<f)
		{
			int t=findflow(y,min(a[k].c,f-s));
			s+=t;a[k].c-=t;a[a[k].other].c+=t;
		}
	}
	if(s==0)h[x]=0;
	return s;
}
int cmp(const void *xx,const void *yy)
{
	node n1=*(node *)xx;
	node n2=*(node *)yy;
	if(n1.c<n2.c)return 1;
	else return -1;
}
bool bk[21000];
int main()
{
	//freopen("milk6.in","r",stdin);
	//freopen("milk6.out","w",stdout);
	int n,m;scanf("%d%d",&n,&m);
	len=0;memset(last,0,sizeof(last));
	for(int i=1;i<=m;i++)
	{
		int x,y,c;scanf("%d%d%d",&x,&y,&c);
		ins(x,y,c);d[i].x=x;d[i].y=y;d[i].c=c;d[i].ds=i;
	}
	st=1;ed=n;
	ll ans=0;
	while(bfs()==true)ans+=findflow(st,inf);
	printf("%lld ",ans);
	qsort(d+1,m,sizeof(node),cmp);
	memset(bk,false,sizeof(bk));int kk=len;
	for(int i=1;i<=m;i++)
	{
		if(d[i].c<=ans)
		{
			memset(last,0,sizeof(last));
			len=0;
			for(int j=1;j<=m;j++)
			{
				if(bk[d[j].ds]==false&&i!=j)ins(d[j].x,d[j].y,d[j].c);
			}
			ll sum=0;
			while(bfs()==true)sum+=findflow(st,inf);
			if(sum+d[i].c==ans)
			{
				ans-=d[i].c;
				bk[d[i].ds]=true;
				b[++lenb]=d[i].ds;
			}
		}
	}
	printf("%d\n",lenb);
	if(lenb!=0)
	{
		sort(b+1,b+lenb+1);
		for(int i=1;i<=lenb;i++)printf("%d\n",b[i]);
	}
	return 0;
}

省选可能会涉及相关问题

  • 12
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值