【COGS】894. 追查坏牛奶

http://cojs.tk/cogs/problem/problem.php?pid=894

题意:n个点m条边的加权网络,求最少边数的按编号字典序最小的最小割。(n<=32, m<=1000)

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
struct Gr {
	static const int N=33, M=1005, oo=~0u>>1;
	struct E { int next, from, to, cap; }e[M<<1];
	int ihead[N], cnt, d[N], p[N], gap[N], cur[N];
	Gr() { memset(ihead, 0, sizeof ihead); cnt=1; }
	Gr & operator=(const Gr &g) {
		memcpy(ihead, g.ihead, sizeof g.ihead);
		memcpy(e, g.e, sizeof g.e);
		cnt=g.cnt;
		return *this;
	}
	void add(int u, int v, int cap) {
		e[++cnt]=(E){ihead[u], u, v, cap}; ihead[u]=cnt;
		e[++cnt]=(E){ihead[v], v, u, 0}; ihead[v]=cnt;
	}
	ll isap(int s, int t, int n) {
		for(int i=0; i<=n; ++i) d[i]=0, gap[i]=0, cur[i]=ihead[i];
		gap[0]=n; int u=s, i, f; ll ret=0;
		while(d[s]<n) {
			for(i=cur[u]; i; i=e[i].next) if(e[i].cap && d[e[i].to]+1==d[u]) break;
			if(i) {
				cur[u]=i; p[e[i].to]=i; u=e[i].to;
				if(u==t) {
					for(f=oo; u!=s; u=e[p[u]].from) f=min(f, e[p[u]].cap);
					for(u=t; u!=s; u=e[p[u]].from) e[p[u]].cap-=f, e[p[u]^1].cap+=f;
					ret+=f;
				}
			}
			else {
				if(!(--gap[d[u]])) break;
				d[u]=n; cur[u]=ihead[u];
				for(i=ihead[u]; i; i=e[i].next) if(e[i].cap && d[e[i].to]+1<d[u]) d[u]=d[e[i].to]+1;
				++gap[d[u]];
				if(u!=s) u=e[p[u]].from;
			}
		}
		return ret;
	}
}g, G;
int n, m, arr[Gr::M], tot;
int main() {
	freopen("milk6.in", "r", stdin);
	freopen("milk6.out", "w", stdout);
	scanf("%d%d", &n, &m);
	for(int i=1; i<=m; ++i) {
		int x, y, cap;
		scanf("%d%d%d", &x, &y, &cap);
		g.add(x, y, cap*(m+1)+1);
	}
	ll ans=0, f;
	G=g;
	f=G.isap(1, n, n);
	for(int i=1; i<=m; ++i) {
		int id=i<<1, cap=g.e[id].cap;
		g.e[id].cap=g.e[id^1].cap=0;
		G=g;
		ll mn=G.isap(1, n, n);
		if(mn+cap==f) arr[++tot]=i, ans+=(cap-1)/(m+1), f=mn;
		else g.e[id].cap=cap, g.e[id^1].cap=0;
	}
	printf("%lld %d ", ans, tot);
	for(int i=1; i<=tot; ++i) printf("%d ", arr[i]);
	return 0;
}

  

神题...在uoj群被神犇们吊打&裱

= =这么水的usaco training我都不会做= =

首先求最少边的话可以直接将权值变为$w*(m+1)+1$,然后就是最小割。理由很简单,最小割是$\sum_{i为一条割边} (w[i]*(m+1)+1) = (m+1)\sum_{i为一条割边} w[i] + c$首先我们分离出了原来没有改变权值的割,显然这样做$\sum_{i为一条割边} w[i]$是原图的最小割,因为乘上$(m+1)$后始终大于边数,和边数$c$都是常数= =。其次我们在求改变权值后的最小割后,比较完原图最小割后还比较了右边常数$c$,而$c$正是割边数。而$(m+1)$这个乘数也是因为割边数<=m最大可能到了m,可能会影响到原来图上的边权值,所以乘上$(m+1)$来消除影响。

那么现在问题变为求普通的字典序最少的最小割。我们考虑从小到大枚举边然后删边。

如果删掉$i$这条边时,最小割变小的值恰好为$i$改变后的权值,那么显然$i$是割边,此时维护的最小割减小,删掉$i$不恢复。

否则把删掉的边恢复。

时间: 2024-10-10 20:12:13

【COGS】894. 追查坏牛奶的相关文章

追查坏牛奶(最大流)

进入今天的正题,追查坏牛奶 思想的话不会人家的玄学求最小割的边数,于是自己想了个神奇的乱搞,先求出最大流,即最小割,然后枚举每条边看是否完全属于割集,然后将其永久去掉 然后将整个输出即可 #include<bits/stdc++.h> using namespace std; #define ll long long const int N=100010; const ll INF=0x7ffffffff; ll m,n,s,t,pre[N],head[N],cnt=1,last[N],dep

USACO 4.4.2 追查坏牛奶 oj1341 网络流最小割问题

描述 Description 你第一天接手三鹿牛奶公司就发生了一件倒霉的事情:公司不小心发送了一批有三聚氰胺的牛奶.很不幸,你发现这件事的时候,有三聚氰胺的牛奶已经进入了送货网.这个送货网很大,而且关系复杂.你知道这批牛奶要发给哪个零售商,但是要把这批牛奶送到他手中有许多种途径.送货网由一些仓库和运输卡车组成,每辆卡车都在各自固定的两个仓库之间单向运输牛奶.在追查这些有三聚氰胺的牛奶的时候,有必要保证它不被送到零售商手里,所以必须使某些运输卡车停止运输,但是停止每辆卡车都会有一定的经济损失.你的

USACO Section 4.4 追查坏牛奶Pollutant Control

http://www.luogu.org/problem/show?pid=1344 题目描述 你第一天接手三鹿牛奶公司就发生了一件倒霉的事情:公司不小心发送了一批有三聚氰胺的牛奶.很不幸,你发现这件事的时候,有三聚氰胺的牛奶已经进入了送货网.这个送货网很大,而且关系复杂.你知道这批牛奶要发给哪个零售商,但是要把这批牛奶送到他手中有许多种途径.送货网由一些仓库和运输卡车组成,每辆卡车都在各自固定的两个仓库之间单向运输牛奶.在追查这些有三聚氰胺的牛奶的时候,有必要保证它不被送到零售商手里,所以必须

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

题目描述 你第一天接手三鹿牛奶公司就发生了一件倒霉的事情:公司不小心发送了一批有三聚氰胺的牛奶.很不幸,你发现这件事的时候,有三聚氰胺的牛奶已经进入了送货网.这个送货网很大,而且关系复杂.你知道这批牛奶要发给哪个零售商,但是要把这批牛奶送到他手中有许多种途径.送货网由一些仓库和运输卡车组成,每辆卡车都在各自固定的两个仓库之间单向运输牛奶.在追查这些有三聚氰胺的牛奶的时候,有必要保证它不被送到零售商手里,所以必须使某些运输卡车停止运输,但是停止每辆卡车都会有一定的经济损失.你的任务是,在保证坏牛奶

luogu 1344 追查坏牛奶(最小割)

第一问求最小割. 第二问求割边最小的最小割. 我们直接求出第二问就可以求出第一问了. 对于求割边最小,如果我们可以把每条边都附加一个1的权值,那么求最小割是不是会优先选择1最少的边呢. 但是如果直接把边的权值+1,这样求得的最小割就不是原来的最小割了,那是因为1会对原来的容量产生影响. 如果把每条边的权值都乘以一个很大的常数,再加上附加权值1,这样求出的最小割是不是显然也是原图的最小割呢. 那么最终的答案除以这个常数就是最小割的容量,最终的答案模这个常数就是最小割的最小割边数. # includ

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

https://www.luogu.org/problemnew/show/P1344 这道题很容易就可以看出是最小割=最大流. 但是要求出要割几条边就有些毒瘤了. ↓为废话 但orzn*inf后,蒟蒻我还是没有想出怎么回事 犹豫好久后,还是悄咪咪点开了题解......... ↑为废话 原来有一个经典的套路: 只需建图时将边权w=w*a+1(w为本来的边权,a为大于1000的数),这样我们能求得最大流ans,则最小割的值为ans/a,割的边数为ans%a. 因为最小割的边集中有w1+w2+w3…

【题解】Luogu P1344 [USACO4.4]追查坏牛奶Pollutant Control

原题传送门 看到这种题,应该一眼就能知道考的是最小割 没错这题就是如此简单,跑两遍最大流(最小割=最大流),一次边权为题目所给,一次边权为1 还有一种优化,优化后只需跑一次最大流,把每条边的权值改成w*MOD+1(MOD为常数,珂以取八位质数233) 答案为maxflow/MOD和maxflow%MOD 基础版本 #include <bits/stdc++.h> #define N 40 #define M 2005 #define inf 0x3f3f3f3f #define getchar

LGOJ1344 追查坏牛奶

Description link 题意概述:给一张图,每条边有边权,求让点 \(1\) 和点 \(n\) 不连通的"最小破坏边权和" 和 "在此基础上的最小破坏边数" 边数 \(\leq 1000\) ,点数 \(\leq 32\) Solution \[Begin\] 其实看出来这个可以用最小割做挺显然的 然后第二问的做法就有点点技巧了 我们把图中的每一条边的边权 \(w_i\) 转化成 \(a \times w_i+1\) 其中\(a\) > \(1000

COGS基本法初稿

COGS基本法 序言 我们COGS人民,为建立更完善的联盟,树立正义,保障网络安宁,提供公共OJ,杜绝极少数恐怖分子对我OJ的破坏行为,并使我们自己和OIER得享自由的幸福,特为COGS制定本基本法. 第一条权利机构 权利机构由老常为领导核心的第一代领导集体及COGS QQ群的元老组成,COGS的权力机构为君主立宪制,其中老常为世袭君主,议会由首相刘易铖,长老王梦迪,内阁大臣张灵犀,外交大臣张子昂.国家工程师李冬麟组成.首相.内阁大臣.外交大臣必须由河南省实验中学有着良好素质和学习水平的学生组成