首页 > 其他分享 >混合图欧拉回路(核心也就是网络流啦)

混合图欧拉回路(核心也就是网络流啦)

时间:2023-02-24 08:22:36浏览次数:39  
标签:int 入度 tot 混合 edge MAXN 回路 欧拉 dis

于2023/2/22日的模拟赛遇到了这一东西。也是网络流应用的一种新模型,感觉是大有可为啊,写个博客记录下。

给定一个图,里面的边有的是有向边,有的是无向边,要求给出无向边的定向方案,使得图中有欧拉回路。如果无解,则输出 \(-1\)。

核心思想就是先随便给无向边定个向,再利用网络流的调整功能来调节边的方向,使得图中有欧拉回路。

步骤:

  • 给所有无向边随便定一个方向,然后计算每个点的出度和入度,建立一个超级源点和超级汇点。
  • 如果一个点的入度大于出度,那么就给它向超级汇点连一条最大流量为 \(\frac{入度-出度}{2}\) 的边。如果一个点的出度大于入度,就从超级源点向它连一条 \(\frac{出度 - 入度}{2}\) 的边。
  • 直接跑网络流,如果满流,则有解,否则无解,输出 \(-1\)。
  • 如果有解的话,就遍历一下无向边,如果在网络流中,这条边满流了,那么就把它反向。最后输出方案即可。

原理:

个人认为最难理解的就是第二点,为什么要这样连边呢?欧拉回路要求的就是使得图中每个点的入度等于出度。如果一个点的入度大于出度,把它与源点相连,流从连接他的边流出,就相当于改变了边的方向,调整了出入度。另一种情况也同理。

无解的时候,为什么图不能满流?无解,就相当于网络流无法将图中的每个点调整为出度等于入度,因此就无解了。

放个板子:

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 1e6;
const int INF = 0x3f3f3f3f;
int id[MAXN + 5],n,m,tot,deg[MAXN + 5],node[MAXN + 5],cno,head[MAXN + 5],s,t,dis[MAXN + 5],cur[MAXN + 5],ans[MAXN + 5],cnt;
bool vis[MAXN + 5];
vector<int> lsh;
struct E{
	int l,r,w;
}e[MAXN + 5];
struct EDGE{
	int u,v,w,next;
}edge[MAXN + 5];
void ADD(int u,int v,int w){
	++tot;
	edge[tot].u = u;
	edge[tot].v = v;
	edge[tot].w = w;
	edge[tot].next = head[u];
	head[u] = tot;
}
void add(int u,int v,int w){
	ADD(u,v,w);
	ADD(v,u,0);
}
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 > 0){
				dis[v] = dis[u] + 1;
				q.push(v);
			}
		}
	}
	if(dis[t])return 1;
	return 0;
}
int dfs(int u,int 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 > 0){
			int di = dfs(v,min(edge[i].w,dist));
			if(di > 0){
				edge[i].w -= di;
				edge[i ^ 1].w += di; 
				return di;
			}
		}
	}
	return 0;
}
int dinic(){
	int an = 0;
	while(bfs()){
		for(int i = s; i <= t; i++){cur[i] = head[i];}
		while(int di = dfs(s,INF))an += di;
	}
	return an;
}
int main(){
	freopen("wait.in","r",stdin);
	freopen("wait.out","w",stdout);
	tot = 1;
	scanf("%d%d",&m,&n);
	for(int i = 1; i <= m; i++){
		scanf("%d%d%d",&e[i].l,&e[i].r,&e[i].w);
		e[i].r++;
		lsh.push_back(e[i].l);
		lsh.push_back(e[i].r);
	}
	sort(lsh.begin(),lsh.end());
	lsh.erase(unique(lsh.begin(),lsh.end()),lsh.end());
	for(int i = 1; i <= m; i++){
		e[i].l = lower_bound(lsh.begin(),lsh.end(),e[i].l) - lsh.begin() + 1;
		e[i].r = lower_bound(lsh.begin(),lsh.end(),e[i].r) - lsh.begin() + 1;
	}
	for(int i = 1; i <= m; i++){
		if(e[i].w == -1){
			add(e[i].l,e[i].r,1);
			ans[tot / 2] = 1;
			deg[e[i].l]++;
			deg[e[i].r]--;
			id[i] = tot;
		}
		else if(e[i].w == 1)deg[e[i].l]++,deg[e[i].r]--;
		else deg[e[i].r]++,deg[e[i].l]--; 
	}
	s = 0,t = lsh.size() + 1;
	for(int i = 1; i <= lsh.size(); i++){
		if(deg[i] >= 0){
			add(s,i,deg[i] / 2);
			cnt += deg[i] / 2;
		}
		else{
			add(i,t,(-deg[i] / 2));
		}
	}
	int k;
	k = dinic();
	if(k < cnt){
		cout << "-1";
		return 0;
	}
	for(int i = 1; i <= m; i++){
		if(e[i].w == -1) cout << (edge[id[i]].w ^ 1) << " ";
		else cout << e[i].w << " ";
	}
}
//4 1000000000
//1 9 -1
//2 6 -1
//1 8 -1
//1 7 -1

利用网络流的动态调整功能,可以解决这样的很多问题。

标签:int,入度,tot,混合,edge,MAXN,回路,欧拉,dis
From: https://www.cnblogs.com/CZ-9/p/17149750.html

相关文章

  • 混合业务场景的TPS计算方式【杭州多测师_王sir】【杭州多测师】
     TPS的计算单业务与混合业务业务的基准测试场景构建单业务测试混合业务测试:登录-资料录入-发短信认证-核保页面渲染+业务处理时间+思考时间=单次业务时间5分钟内完成2000......
  • 华为认证欧拉openEuler-HCIA文本编辑器及文本处理
    文本编辑器及文本处理文本编辑器介绍常见的Linux文本编辑器有:emacsnanogeditkeditvivimLinux文本编辑器-emacsemacs是一款功能强大的编辑器,与其说是一款编辑器,它更像......
  • day76-mixins混合,plugins插件,scoped混合
    mixins混合把多个组件公用的配置属性提取成一个混入对象先配置minins.js文件exportconstmixin={methods:{showName(){alert(this.......
  • 性能测试-混合场景
    1、问题-我的脚本,期望在启动之后,运行一段时间,暂停,然后过一段时间之后,再运行?1、jenkins中的定时任务√但是,这种方式,需要大家掌握Jenkins中定时任务的配置2、UltimateT......
  • less和scss的混合(mixin)使用
    在我们写样式时候,经常会有样式书写的都是一样的,只是有些值不一样而已,但我们却要重复的去写,感觉相当的麻烦。比如给一个按钮写样式,不同的size,尺寸不同,但样式都是一样的,重复......
  • 基于二进制编码遗传优化的混合发电系统配置优化问题求解
    up目录一、理论基础二、核心程序三、测试结果一、理论基础首先,传统的遗传优化算法,其标准的优化过程如下所示:步骤一:根据所需要处理的问题特点,选择问题解对应的编码,并......
  • 最快素数打表,比欧拉筛快一倍。
    1e7内比欧拉筛子快一倍,2e7持平,之后略慢不论N多大整体计算次数,都是欧拉筛子的1/3,求大神解答1e8之后为什么变慢思路:相较于欧拉筛考虑1-n所有数,这里基于孪生素数,只需要考虑......
  • 目标跟踪之高斯混合模型---cv实现
    #include<stdio.h>#include<cv.h>#include<cxcore.h>#include<highgui.h>#include<cvaux.h>//必须引此头文件voidmain(  ){   //参数初始化定义    IplIma......
  • #10105. 「一本通 3.7 例 1」欧拉回路
     求欧拉回路(dfs) #include<bits/stdc++.h>usingnamespacestd;constintN=1e6+3,M=2e6+3;inlineintread(){intres=0,flag=1;ch......
  • 欧拉路 笔记
    欧拉路:从S到T不重复地经过图的所有边 存在性判定:有2个奇点(S,T),其他为偶点 欧拉回路:同欧拉路,但要求回到起点欧拉图:含有欧拉回路的图判定:(1)对无向图,所有点的度......