题解 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\to x\) 及 \(y\to T\) 这两条边.

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

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

code

\(\texttt{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\n",ans-DINIC());
	return 0;
}

原文地址:https://www.cnblogs.com/permzf/p/12666570.html

时间: 2024-10-14 07:08:45

题解 51nod2935 土地划分的相关文章

BZOJ3511 土地划分 题解&amp;代码

pkusc发现自己不会费用流233333于是两天速成费用流[然而这是一道最小割(最大流QwQ 题意: 给出n个点m条边,并设定: 点x在被划分至集合A时获得权值A[x],否则即被划分至集合B并获得权值B[x]: 边(x,y)连接的x和y均属于集合A时获得权值ea,均属于集合B时获得权值eb,否则获得权值-ec. 题解:这题-反正我是没自己建出图来. 对于点x,从S(代表集合A)向x连容量为va的边,从x向T(代表集合B)连容量为vb的边. 对于边(x,y),从S向x和y分别连容量为ea/2的边,

洛谷 P1079 Vigen&#232;re 密码 题解

此文为博主原创题解,转载时请通知博主,并把原文链接放在正文醒目位置. 题目链接:https://www.luogu.org/problem/show?pid=1079 题目描述 16 世纪法国外交家 Blaise de Vigenère 设计了一种多表密码加密算法――Vigenère 密 码.Vigenère 密码的加密解密算法简单易用,且破译难度比较高,曾在美国南北战争中为 南军所广泛使用. 在密码学中,我们称需要加密的信息为明文,用 M 表示:称加密后的信息为密文,用 C 表示:而密钥是一种

8.8联考题解

今天的T1让我怀疑我是不是在做奥赛题--这考的是什么知识点啊这个,会不会用绝对值函数? Evensgn 的债务 时间限制: 1 Sec  内存限制: 128 MB 题目描述 Evensgn 有一群好朋友,他们经常互相借钱.假如说有三个好朋友A,B,C.A 欠 B 20 元,B 欠 C 20 元,总债务规模为 20+20=40 元.Evensgn 是个追求简约的人,他觉得这样的债务太繁杂了.他认为,上面的债务可以完全等价为 A 欠C20 元,B 既不欠别人,别人也不欠他.这样总债务规模就压缩到了 

POJ 2533 - Longest Ordered Subsequence(最长上升子序列) 题解

此文为博主原创题解,转载时请通知博主,并把原文链接放在正文醒目位置. 题目链接:http://poj.org/problem?id=2533 Description A numeric sequence of ai is ordered if a1 < a2 < ... < aN. Let the subsequence of the given numeric sequence (a1, a2, ..., aN) be any sequence (ai1, ai2, ..., aiK)

(leetcode题解)Pascal&#39;s Triangle

Pascal's Triangle  Given numRows, generate the first numRows of Pascal's triangle. For example, given numRows = 5,Return [ [1], [1,1], [1,2,1], [1,3,3,1], [1,4,6,4,1] ] 题意实现一个杨辉三角. 这道题只要注意了边界条件应该很好实现出来,C++实现如下 vector<vector<int>> generate(int

2017ZZUACM省赛选拔试题部分题解----谨以纪念我这卡线滚粗的美好经历

写在前面: 其实心里有些小小的不爽又有点小小的舒畅,为啥捏?不爽当然是因为没被选拔上啦,舒畅捏则是因为没被选拔上反而让自己警醒,学长也提点很多很多."沉下去,然后一战成名"学长如是对我说,我很开心.其实这完全算不算是题解,只是我个人的一些小想法而已.而且到现在还有一题不会...让自己长点记性吧. 题目 A :聪明的田鼠 Time Limit: 1 Sec Memory Limit: 128 MB Description 田鼠MIUMIU来到了一片农田,农田可以看成是一个M*N个方格的矩

LeetCode-001题解

此题目摘自LeetCode001 Given an array of integers, find two numbers such that they add up to a specific target number. The function twoSum should return indices of the two numbers such that they add up to the target, where index1 must be less than index2.

leetcode题解: Next Permutation

最近还一直在刷leetcode,当然,更多时候只是将题解写在自己的电脑上,没有分享出来.偶尔想起来的时候,就写出来. public class Solution { public void nextPermutation(int[] nums) { if(nums==null||nums.length<=1) return; nextPermutationHelp( nums,0,nums.length-1); } public void nextPermutationHelp(int []nu

HDU 5014 Number Sequence(2014 ACM/ICPC Asia Regional Xi&#39;an Online) 题解

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5014 Number Sequence Problem Description There is a special number sequence which has n+1 integers. For each number in sequence, we have two rules: ● ai ∈ [0,n] ● ai ≠ aj( i ≠ j ) For sequence a and sequ