【BZOJ 2400】Spoj 839 Optimal Marks 最小割

很有意思的一道题,看到网上有先跑最小割然后dfs的做法,但是还看到一个比较有趣的建图方法。

首先对于题目来说,显然可以因为每一个位之间都不会相互影响所以可以按位处理,枚举每一位然后把每一个点划分为0或者1,这样一来就相当于把每一个元素划分为两个集合,并且要求代价最小,这样可以想到最小割。

然后对于这一道题目要求在保证边权最小的情况下点权和最小,这就相当于要在保证第一条件最优下次要条件也最优,这样我们在网络流中把第一条件的每条边权都扩大10000倍这样次要条件就不会影响到第一条件了(这种思想其实以前遇到过一次)

具体的:

次要条件:s代表0集合,t代表1集合,如果这个点已经确定为1 s->i边权为1 i->t边权为inf这样代表代价必须为1

如果这个点确定为0  s->i边权为inf 不会被割掉

没有确定 s-> 边权为1 可割可不割

第一条件:每一条边对应原图中的边相连边权扩大10000倍

#include
#include
#include
#define maxn 100021
#define inf 100000000000000ll
#define LL long long
using namespace std;
void read(LL& x){
	x=0;char c=getchar();LL f=1;
	for(;c>'9'||c<'0';c=getchar())if(c=='-')f=-1;
	for(;c>='0'&&c<='9';c=getchar())x=x*10+c-'0';
	x*=f;
}
LL n,m,tot=1,head[maxn],last[maxn],q[maxn];
LL h[maxn],s,t,w[maxn],bin[55],ans1,ans2;
struct data{LL a,b;}ed[maxn];
struct edge{LL v,next,w;}e[maxn];
void adde(LL a,LL b,LL c){
	e[++tot].v=b;e[tot].next=head[a],e[tot].w=c;
	head[a]=tot;
	e[++tot].v=a;e[tot].next=head[b],e[tot].w=0;
	head[b]=tot;
}
bool bfs(){
	for(LL i=0;i<=t;i++)h[i]=-1;
	LL l=0,r=1;
	q[l]=s,h[s]=0;
	while(l=0;i--)
		solve(bin[i]);
	printf("%lld\n%lld",ans1,ans2);
	return 0;
}


你可能感兴趣的:(ac之路,bzoj,网络流)