题解 51nod2935 土地划分

题解 51nod2935 土地划分

题面

51nod

解析

一眼最小割考虑怎么建图.

从最简单的边连起:对于每个点 (i),连边 ((S,i,A_i)),((i,T,B_i)),

((S,T) 分别为源,汇点)

然后考虑每条边 ((x,y))的问题,

如果两个点都划分给 (A),那在图上就是两个点到 (T) 的边都被割掉了,

因此我们新建一个点 (z) ,连边 ((x,z,inf),(y,z,inf),(z,T,EB_i))

即割掉都划分给 (B) 的收益.

而都划分给 (B) 的连边方式同理,这里就不再赘述.

(如果硬是不知道可以看代码)

然后考虑 (EC) 的影响,不妨设图中还存在 (S o x)(y o T) 这两条边.

那么我们要割掉 (EC) 的代价.

对于边 ((x,y)),连边 ((x,y,EC_i),(y,x,EC_i)) 即可.

code

( exttt{DINIC}) 加点优化就能过?

#include <iostream>
#include <stdio.h>
#include <cstring>
#include <queue>
#define ll long long
#define filein(a) freopen(a,"r",stdin)
#define fileout(a) freopen(a,"w",stdout);
using namespace std;

inline int read(){
	int sum=0,f=1;char c=getchar();
	while((c<'0'||c>'9')&&c!=EOF){if(c=='-') f=-1;c=getchar();}
	while(c>='0'&&c<='9'&&c!=EOF){sum=sum*10+c-'0';c=getchar();}
	return sum*f;
}

const int N=50005;
const int INF=0x3f3f3f3f;
struct val{int a,b,c,x,y;}v[N<<1];
int n,m,S,T;ll ans;

namespace nw{
	struct edge{int to,next,v;}e[N<<4];
	int head[N<<3],cnt=1;
	int d[N<<3],cur[N<<3];
	queue<int> que;
	inline void add(int x,int y,int v){
		e[++cnt]=(edge){head[x],y,v};head[x]=cnt;
		e[++cnt]=(edge){head[y],x,0};head[y]=cnt;
	}
	inline bool bfs(){
		memset(d,0,sizeof(d));
		memcpy(cur,head,sizeof(cur));
		que.push(S);d[S]=1;
		while(!que.empty()){
			int x=que.front();que.pop();
			for(int i=head[x];i;i=e[i].to){
				int k=e[i].next;
				if(d[k]||!e[i].v) continue;
				d[k]=d[x]+1;que.push(k);
			}
		}
		return d[T];
	}
	inline int dfs(int x,int mi){
		if(x==T||!mi) return mi;
		int flow=0;
		for(int &i=cur[x];i;i=e[i].to){
			int k=e[i].next;
			if(!e[i].v||d[k]!=d[x]+1) continue;
			int ret=dfs(k,min(mi,e[i].v));
			mi-=ret;flow+=ret;
			e[i].v-=ret;e[i^1].v+=ret;
			if(!mi) break;			
		}
		if(mi) d[x]=-1;
		return flow;
	}
	inline ll DINIC(){
		ll ret=0;
		while(bfs()) ret+=dfs(S,INF);
		return ret;
	}
}
using namespace nw;

int main(){
	n=read();m=read();S=1;T=n;
	for(int i=2;i<n;i++) v[i].a=read();
	for(int i=2;i<n;i++) v[i].b=read();
	for(int i=n+1;i<=n+m;i++){
		v[i].x=read(),v[i].y=read();
		v[i].a=read(),v[i].b=read(),v[i].c=read();
	}
	for(int i=2;i<n;i++){
		ans+=v[i].a+v[i].b;
		add(S,i,v[i].a);add(i,T,v[i].b);
	}
	for(int i=n+1;i<=n+m;i++){
		ans+=v[i].a+v[i].b;
		add(v[i].x,v[i].y,v[i].c);add(v[i].y,v[i].x,v[i].c);
		add(S,i,v[i].a);add(i+m,T,v[i].b);
		add(i,v[i].x,INF);add(i,v[i].y,INF);
		add(v[i].x,i+m,INF);add(v[i].y,i+m,INF);
	}
	printf("%lld
",ans-DINIC());
	return 0;
}
原文地址:https://www.cnblogs.com/permzf/p/12666570.html