[最大权闭合子图小练]

[POJ 2987]每个人都为公司带来一个收益,公司老板要裁员(当然是业绩不好给公司带来负收益的人被裁掉啦~),然而踢走一个人会把他的下属都踢走,求最大收益

最大权闭合子图~,其实就是最小割啦,此题要求最小化走的人数,然而就是最小割中的人数QAQ(并不知道为什么),dfs(S)相关的点

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#define maxn 100010
using namespace std;

typedef long long ll;

const int inf = 0x7fffffff;

int n, m;

struct Edge{
	int to, next, w;
	Edge(int v = 0, int nxt = 0, int d = 0){
		to = v, next = nxt, w = d;
	}
}edge[maxn * 5];
int h[maxn], cnt = 1, S, T;

void add(int u, int v, int w){
	edge[++ cnt] = Edge(v, h[u], w); h[u] = cnt;
	edge[++ cnt] = Edge(u, h[v], 0); h[v] = cnt;
}

queue<int> Q;

int d[70000];

bool BFS(){
	memset(d, -1, sizeof d);
	d[S] = 0; Q.push(S);
	while(!Q.empty()){
		int u = Q.front(); Q.pop();
		for(int i = h[u]; i; i = edge[i].next){
			if(!edge[i].w)continue;
			int v = edge[i].to;
			if(d[v] == -1) d[v] = d[u] + 1, Q.push(v);
		}
	}return d[T] != -1;
}

int cur[maxn];

ll DFS(int x, ll a){
	if(x == T || a == 0)
	    return a;
	int used = 0, f;
	for(int i = cur[x]; i; i = edge[i].next){
		int v = edge[i].to;
		if(d[v] == d[x] + 1 && edge[i].w){
			f = DFS(v, min(a-used, (ll)edge[i].w));
			edge[i].w -= f;
			edge[i^1].w += f;
			used += f;
			if(f > 0)cur[x] = i;
			if( used == a)return used;
		}
	}
	if(used == 0)d[x] = -1;
	return used;
}

ll Dinic(){
	ll ret = 0;
	while(BFS()){
		for(int i = S; i <= T; i ++)
		    cur[i] = h[i];
		ret += DFS(S, inf);
	}
	return ret ;
}

bool vis[maxn];

void dfs(int u){
	vis[u] = true;
	for(int i = h[u]; i; i = edge[i].next){
		int v = edge[i].to;
		if(edge[i].w && !vis[v])
		    dfs(v);
	}
}

int main(){
	scanf("%d%d", &n, &m);
	S = 0, T = n + m + 1;
	int b;

	ll sum = 0;
 	for(int i = 1; i <= n; i ++){
		scanf("%d", &b);
		if(b > 0){
			add(S, i, b);
			sum += b;
		}
		else add(i, T, -b);
 	}
 	int u, v;
 	for(int i = 1; i <= m; i ++){
		scanf("%d%d", &u, &v);
		add(u, v, inf);
 	}
 	sum -= Dinic();
 	dfs(S);
 	int ans = 0;
 	for(int i = 1; i <= n; i ++)
 	    ans += vis[i];
 	printf("%d %lld\n", ans, sum);
	return 0;
}

[HDU 3879]建立一个新站点需要Pi的花费,给定m个客户使用两个站点所带来的收益Ci,最大化收益

把每一个客户新建一个点然后建图QAQ,不能在原图上直接连边。。只贴建图了QAQ。。

while(scanf("%d%d", &n, &m) == 2){
	memset(h, 0, sizeof h); cnt = 1;
	int p; S = 0, T = n + m + 1;
	for(int i = 1; i <= n; i ++){
		scanf("%d", &p);
		add(S, i, p);
	}
	int u, v, w, sum = 0, size = n;
	for(int i = 1; i <= m; i ++){
		scanf("%d%d%d", &u, &v, &w);
		++ size;
		add(u, size, inf);
		add(v, size, inf);
		add(size, T, w);
		sum += w;
	}
	printf("%d\n", sum - Dinic());
}

[HDU 4971]

The first line of the input is a single integer T(<=100) which is the number of test cases.

Each test case contains a line with two integer n(<=20) and m(<=50) which is the number of project to select to complete and the number of technical problem.

Then a line with n integers. The i-th integer(<=1000) means the profit of complete the i-th project.

Then a line with m integers. The i-th integer(<=1000) means the cost of training to solve the i-th technical problem.

Then n lines. Each line contains some integers. The first integer k is the number of technical problems, followed by k integers implying the technical problems need to solve for the i-th project.

After that, there are m lines with each line contains m integers. If the i-th row of the j-th column is 1, it means that you need to solve the i-th problem before solve the j-th problem. Otherwise the i-th row of the j-th column is 0.

就是有问题和工程,解决问题是有关联性的而且要花费代价,解决一些问题可以去做某工程带来一些收益,求最大化收益

最重要的是建图啦。。

for(int dir = 1; dir <= test; dir ++){
	memset(h, 0, sizeof h);
	int sum = 0, p, k;
	scanf("%d%d", &n, &m);
	cnt = 1, S = 0, T = n + m + 1;
	for(int i = 1; i <= n; i ++){
		scanf("%d", &p);
		add(S, i, p);
		sum += p;
	}

	for(int i = 1; i <= m; i ++){
		scanf("%d", &p);
		add(i + n, T, p);
	}

	for(int i = 1; i <= n; i ++){
		scanf("%d", &k);
		for(int j = 1; j <= k; j ++){
			scanf("%d", &p); p ++;
			add(i, p + n, inf);
		}
	}

	for(int i = 1; i <= m; i ++){
		for(int j = 1; j <= m; j ++){
			scanf("%d", &p);
			if(p == 1) add(i + n, j + n, inf);
		}
	}
	printf("Case #%d: %d\n", dir, sum - Dinic());
}

  

时间: 2024-07-29 21:12:31

[最大权闭合子图小练]的相关文章

hiho一下 第119周 #1398 : 网络流五&#183;最大权闭合子图 【最小割-最大流--Ford-Fulkerson 与 Dinic 算法】

#1398 : 网络流五·最大权闭合子图 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 周末,小Hi和小Ho所在的班级决定举行一些班级建设活动. 根据周内的调查结果,小Hi和小Ho一共列出了N项不同的活动(编号1..N),第i项活动能够产生a[i]的活跃值. 班级一共有M名学生(编号1..M),邀请编号为i的同学来参加班级建设活动需要消耗b[i]的活跃值. 每项活动都需要某些学生在场才能够进行,若其中有任意一个学生没有被邀请,这项活动就没有办法进行. 班级建设的活

NOI2006 最大获利(最大权闭合子图)

codevs 1789 最大获利 2006年NOI全国竞赛 时间限制: 2 s 空间限制: 128000 KB 题目描述 Description 新的技术正冲击着手机通讯市场,对于各大运营商来说,这既是机遇,更是 挑战.THU 集团旗下的 CS&T 通讯公司在新一代通讯技术血战的前夜,需要做 太多的准备工作,仅就站址选择一项,就需要完成前期市场研究.站址勘测.最 优化等项目. 在前期市场调查和站址勘测之后,公司得到了一共 N 个可以作为通讯信号中 转站的地址,而由于这些地址的地理位置差异,在不同

最大权闭合子图 - [求最大点权的闭合子图]

引用来自http://www.cnblogs.com/wuyiqi/archive/2012/03/12/2391960.html的思想: 首先有一个有向连通图,每个点带有一个权值,例如: 此时,构建一个超级源点s,一个超级汇点t,所有的点按权值的正负连接到s和t上,转换成一个边权值有向图,如下图: (注:点权为0的点可以忽略,对结果没有影响) 这时,可以得到小结论: ①该带边权有向图的关于s-t最小割,是简单割: 简单割:割集中所有的边,都与s或t相连接. 显然的,因为不与s,t相连的边,权值

最大权闭合子图

所谓闭合子图就是给定一个有向图,从中选择一些点组成一个点集V.对于V中任意一个点,其后续节点都仍然在V中.比如: 在这个图中有8个闭合子图:?,{3},{4},{2,4},{3,4},{1,3,4},{2,3,4},{1,2,3,4} 小Ho:闭合子图我懂了,但是这跟我们这次的问题有啥关系呢? 小Hi:我们先把这次的问题转化为2分图.将N个活动看作A部,将M个学生看作B部.若第i个活动需要第j个学生,就连一条从A[i]到B[j]的有向边.比如对于例子: 假如选择A[1],则我们需要同时选择B[1

poj 2987 Firing【最大权闭合子图+玄学计数 || BFS】

玄学计数 LYY Orz 第一次见这种神奇的计数方式,乍一看非常不靠谱但是仔细想想还卡不掉 就是把在建图的时候把正权变成w*10000-1,负权变成w*10000+1,跑最大权闭合子图.后面的1作用是计数,因为在最大权闭合子图中划到s点一侧的代表选,这样一来,后四位就是起了计数作用.sum初始统计的个数就是所有正权点,然后dinic中割掉一个正权点的边即相当于在最终答案的后四位+1,也就是点数-1 然后考虑收益相同的方案,点数多的后四位一定小,而当前求得又是最小割,所以会选割掉点数少的,也就是留

我和最大权闭合子图

第一次接触最大权闭合子图大概是2017年3月27号星期一,那段时间有5个同学(ZJC/LKQ/LWD/WJJ/...)去了湖南师大附中听PTY.BK他们讲课,因为我没有去Hfu一直很怪罪.后来安排我和LXY在70去电子科大之前去考一周的试,上午LXY的Mom接送,下午我们坐metro到世纪城再让LXY的Mom送回学校上晚自习.那一天我去70,T1是分治Floyd,T2是轮廓线DP,T3是一道最大权闭合子图(后来知道是BZOJ 3774 最优选择).那时我只会Dinic的模板,我的初高中学长Ana

HDU5772 String problem(最大权闭合子图)

题目..说了很多东西 官方题解是这么说的: 首先将点分为3类 第一类:Pij 表示第i个点和第j个点组合的点,那么Pij的权值等于w[i][j]+w[j][i](表示得分) 第二类:原串中的n个点每个点拆出一个点,第i个点权值为 –a[s[i]] (表示要花费) 第三类:对于10种字符拆出10个点,每个点的权值为  -(b[x]-a[x]) 那么我们可以得到一个关系图 ,对于第一类中的点Pij,如果想要选择Pij,你就必须要选中第二类中的点i和j,对于第二类中的点如果你想选中第i个点,其对应的字

[BZOJ 1497][NOI 2006]最大获利(最大权闭合子图)

题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1497 分析: 这是在有向图中的问题,且边依赖于点,有向图中存在点.边之间的依赖关系可以考虑最大权闭合子图 假设a与b之间有权值为c的边(根据题意是双向边) 那么我们可以建一个新节点,点的权值为c,并指向a点和b点(单向),同时断掉原本a,b之间的双向边,a,b的点的权值是它们的花费(负的) 那么对于原问题就转化成了求最大权闭合子图的问题了 ——————————————————————

hdu 3996 Gold Mine 最大权闭合子图

Gold Mine Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 2374    Accepted Submission(s): 514 Problem Description Long long ago, there is a gold mine.The mine consist of many layout, so some are