首页 > 其他分享 >生草——网络流知识点等梳理

生草——网络流知识点等梳理

时间:2023-02-13 22:37:28浏览次数:37  
标签:知识点 int double 点权 tot edge 生草 梳理 dis

服了,看来只写题解不系统总结的博客并不能十分有效地提高对知识点的理解程度。还是得回归到以前既总结知识本身,又写题解的形态。否则就会落到今天这个下场——知识点大量遗忘,会的题也不会做了……这里大概说说网络流的一些脱产应用(我最容易忘的一些),后续还会添加如何应用这些东西的思想罢。

最大权闭合子图

定义:

一个有向图 \(G = (V,E)\) 的闭合图是该有向图的一个点集,且该点集的所有出边都指向该点集,即闭合图内的任意后继也一定在闭合图中。

如何求解:

思路:建图,利用最小割模型来解。

设定一个源点 \(s\),将 \(s\) 向所有点权为 \(v(v > 0)\) 的点连一条最大流量为 \(v\) 的边。设定一个汇点 \(t\),从所有点权为 \(v(v < 0)\) 的点向汇点 \(t\) 连一条最大流量为 \(-v\) 的边。再将原图中所有边在新建的图中相连,容量为正无穷。跑一遍最小割,用总点权减去跑出来的点权即可。

最大密度子图

定义:一个无向图 \(G = (V,E)\) 的密度 \(D\) 为该图的边数 \(E\) 与该图的点数 \(V\) 的比值 \(D = \frac{|E|}{|V|}\)。给出一个无向图 \(G = (V,E)\),其具有最大密度的子图 \(G'=(V',E')\) 称为最大密度子图,即最大化 \(D'=\frac{E'}{V'}\)

解决方法:

对 \(D\) 换一种写法:

\[D = f(x) = \frac{\sum_{e \in E}x_e}{\sum_{v \in V}x_v} \]

\(x_e\) 若等于 \(1\),则表示选择了 \(e\) 这条边,\(x_v\) 亦如此。
你需要对每一个 \(v\) 做出选还是不选的决定,对每一个 \(e\),如果选择它,就必须也选择它的两个端点(又是一种捆绑的感觉)。

我们不妨考虑下分数规划。

构造一个新函数:

\[h(g) = \max(\sum_{e \in E}x_e - \sum_{v \in V}g * x_v) \]

因为此时所有点的点权为 \(1\),所以枚举一个 \(g\) 就相当于把选的这些点的点权全部赋值为 \(g\),根据这些点推出所必须选的边的数量,然后就可以根据 \(h(g)\) 的正负判断结果了。

\[\left\{ \begin{matrix} h(g) = 0 \to g = D_{max}\\ h(g) < 0 \to g > D_{max}\\ h(g) > 0 \to g < D_{max}\\ \end{matrix} \right. \]

}

有一个小结论:同一个图内两种密度的差最小为 \(\frac{1}{n^2}\),算很显然的了吧。
贴个板子~

#include<bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
const double eps = 1e-8; 
const int MAXN = 1e5;
int n,m,tot,cnt,dis[MAXN + 5],head[MAXN + 5],cur[MAXN + 5],s,t,x[MAXN + 5],y[MAXN + 5];
struct EDGE{
	int u,v,next;
	double w;
}edge[MAXN + 5];
void ADD(int u,int v,double w){
	++tot;
	edge[tot].next = head[u];
	edge[tot].u = u;
	edge[tot].v = v;
	edge[tot].w = w;
	head[u] = tot;
}
void add(int u,int v,double w){
	ADD(u,v,w);
	ADD(v,u,0);
}
void build(double r){
	tot = 1;
	cnt = n;
	memset(head,0,sizeof head);
	memset(edge,0,sizeof edge);
	for(int i = 1; i <= m; i++){
		++cnt;
		add(s,cnt,1);
		add(cnt,x[i],INF);
		add(cnt,y[i],INF);  
	}
	t = ++cnt;
	for(int i = 1; i <= n; i++)add(i,t,r);
}
bool bfs(){
	queue<int> q;
	q.push(s);
	memset(dis,0,sizeof dis);
	dis[s] = 1;
	while(!q.empty()){
		int u = q.front();
		q.pop();
		for(int i = head[u]; i; i = edge[i].next){
			int v = edge[i].v;
			if(!dis[v] && edge[i].w > eps){
				dis[v] = dis[u] + 1;
				q.push(v);
			}
		}
	}
	if(dis[t])return 1;
	return 0;
}
double dfs(int u,double dist){
	if(u == t)return dist;
	for(int &i = cur[u]; i; i = edge[i].next){
		int v = edge[i].v;
		if(dis[v] == dis[u] + 1 && edge[i].w > eps){
			double di = dfs(v,min(dist,edge[i].w));
			if(di > eps){
				edge[i].w -= di;
				edge[i ^ 1].w += di;
				return di;
			}
		}
	}
	return 0;
}
double dinic(){
	double aans = 0;
	while(bfs()){
		for(int i = 0; i <= cnt; i++)cur[i] = head[i];
		while(double di = dfs(s,INF))aans += di;
	}
	return aans;
}
bool check(double r){
	build(r);
	double b = dinic();
	return m - b > eps;
}
int vis[MAXN + 5],ans;
void DFS(int u)
{
	vis[u] = 1, ans += (u <= n);
	for(int i = head[u]; i; i = edge[i].next)
		if(edge[i].w >= eps && !vis[edge[i].v]) DFS(edge[i].v);
}
int main(){
	scanf("%d%d",&n,&m);
	if(m == 0){cout << 1;return 0;}
	for(int i = 1; i <= m; i++){
		scanf("%d%d",&x[i],&y[i]);
	}	
	double l = 0,r = m,mn = 1.0 / n / n;
	while(l + mn < r){
		double mid = (l + r) / 2.0;
		if(check(mid))l = mid;
		else r = mid; 
	}
	check(l);
	DFS(s);
	cout << ans - 1;
}

二分图的最大匹配

定义:

给定一个二分图,从这个图中的所有边挑一些边出来形成一个新边集,使得集合中任意两条边都没有公共点。这样的一个边集叫二分图的一个匹配。而这种元素最多的集合称为二分图的最大匹配。

解决方法:

将二分图分为左部和右部。从源点向左部每一个点各连一条最大容量为 \(1\) 的边,从右部的所有点向汇点各连一条最大容量为 \(1\) 的边。将原图中所有无向边的方向全改为从左部到右部,最大容量为正无穷。把这些边加入到新建的图中,跑一遍最大流即可。

二分图的最小点权覆盖集

定义:

点覆盖集是无向图 \(G\) 的一个点集,使得该图中所有边都至少有一个端点在这个集合内。而最小点覆盖集就是点数最少的覆盖集。

解决方法:

有个定理,二分图的最小点权覆盖集等于二分图的最大匹配……

二分图的最大点权独立集

定义:

点独立集就是在一个无向图中选一些点,使这些点两两间没有边相连即可。

解决方法:

所有点的数量减去最小点权覆盖集即可。

标签:知识点,int,double,点权,tot,edge,生草,梳理,dis
From: https://www.cnblogs.com/CZ-9/p/17117009.html

相关文章

  • Linux知识点
    Linux虚拟化所需工具:https://pan.baidu.com/s/1643-kYcx9oPGnGEZM1pLOw?pwd=g0v5提取码:g0v5基础包#解决在7的版本中没有ifconfig命令,加上-y不用手动确认yuminstall......
  • java的知识点
    java知识点1、包装类自带有parse方法Integeri=315;inti1=Integer.parseInt("315");System.out.println(i==i1);Longl1=45......
  • css知识点
    1.css盒模型:盒子的组成:内容content,内边距padding,边框border,外边距margin盒模型的类型:标准盒模型:margin+padding+border+contentIE盒模型:margin+content(包含了bo......
  • 30个Javascript知识点总结,总有你不会的!
    最近重温了一遍红宝书,发现一些比较好玩的写法,很多东西日常都在用,但是发现还会有不一样的写法,结合一些日常工作中使用的方法,为大家总结一篇日常经常使用可能还不知道的点,希......
  • 30个Javascript知识点总结,总有你不会的!
    近重温了一遍红宝书,发现一些比较好玩的写法,很多东西日常都在用,但是发现还会有不一样的写法,结合一些日常工作中使用的方法,为大家总结一篇日常经常使用可能还不知道的点,希望......
  • 初中数学《概率初步》知识点梳理
    基本概念:随机事件:事件分为确定事件(又分为必然事件和不可能事件)和随机事件(又叫不确定事件)。必然事件:在一定条件下重复进行试验时,在每次试验中必然会发生的事件。不可能事件:......
  • spring 知识点
    概述以及IOC理论推导Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器(框架)。Spring框架是一个分层架构,由7个定义良好的模块组成。Spring模块构建在核心容器......
  • Java基础知识点(if语句的第二种和第三种)
    一:if语句的第二种格式1.格式:if(关系表达式){语句体1;​}else{语句体2;}2.执行流程:1.首先计算关系表达式的值。2.如果关系表达式的值为true,就执行语句体1.3.如果关系表达式的值......
  • Java基础知识点(条件控制语句之if语句)
    1.顺序结构:Java程序中默认的执行流程,按照代码的先后顺序,从上到下依次进行。2.选择结构语句<1>.if语句格式:if(关系表达式){语句体;}执行流程:1.首先计算关系表达式的值。2.如......
  • JMM知识点总结
    JMM知识点总结一、什么是JMM?不知道大家在学习的过程有没有思考过这两个问题为什么说java是跨平台语言导致并发问题的原因是什么第一个问题,我是这么理解的,代码运行本......