首页 > 其他分享 >欧拉回路 模版dfs stack两种版本

欧拉回路 模版dfs stack两种版本

时间:2024-08-20 17:39:03浏览次数:10  
标签:表示 idx int 模版 ne dfs ++ type stack

stack堆栈代替dfs版本

// 欧拉模版.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

/*
* https://loj.ac/p/10105
有一天一位灵魂画师画了一张图,现在要你找出欧拉回路,即在图中找一个环使得每条边都在环上出现恰好一次。

一共两个子任务:

这张图是无向图。(50 分)

这张图是有向图。(50 分)

输入格式
第一行一个整数 t,表示子任务编号。t \in \{1, 2\},如果 t = 1 则表示处理无向图的情况,如果 t = 2 则表示处理有向图的情况。

第二行两个整数 n, m,表示图的结点数和边数。

接下来 m 行中,第 i 行两个整数 v_i, u_i,表示第 i 条边(从 1 开始编号)。保证 1 \leq v_i, u_i \leq n。

如果 t = 1 则表示 v_i 到 u_i 有一条无向边。

如果 t = 2 则表示 v_i 到 u_i 有一条有向边。

图中可能有重边也可能有自环。

输出格式
如果不可以一笔画,输出一行 NO。

否则,输出一行 YES,接下来一行输出一组方案。

如果 t = 1,输出 m 个整数 p_1, p_2, ~~~~~~, p_m。令 e = \lvert p_i \rvert,那么 e 表示经过的第 i 条边的编号。如果 p_i 为正数表示从 v_e 走到 u_e,否则表示从 u_e 走到 v_e。

如果 t = 2,输出 m 个整数 p_1, p_2, ~~~~~~, p_m。其中 p_i 表示经过的第 i 条边的编号。


1
3 3
1 2
2 3
1 3

YES
1 2 -3



2
5 6
2 3
2 5
3 4
1 2
4 2
5 1

YES
4 1 3 5 2 6


数据范围与提示
1<=n<=10^5 0<=m<=2*10^5
*/

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <cstring>
#include <deque>

using namespace std;

const int N = 100010, M = 400010;
int h[N], e[M], ne[M], idx;
int n, m; int type;
int din[N], dout[N];
int cnt; int ans[M];
int used[M];
bool vis[M];
int stack_[M];
int top;
deque<int> st;

void add(int a, int b) {
	e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}

void euler(int u) {
	stack_[++top] = u;
	while (top > 0) {
		int x = stack_[top], i = h[x];
		while (i!=-1 && vis[i]) i = ne[i];
		if (i != -1) {
			stack_[++top] = e[i];
			h[x] = ne[i];
			vis[i] = true;
			if (type == 1) {
				vis[i ^ 1] = true;
			}

			if (type == 1) {
				int idx = i / 2 + 1;
				if (i % 2 == 1) idx = -idx;
				st.push_back(idx);
			}
			else {
				st.push_back(i+1);
			}
		}
		else {
			top--;
			if (!st.empty())
			{
				ans[++cnt] = st.back(); st.pop_back();
			}
		}
	}
}


int main() {
	scanf("%d", &type);
	scanf("%d%d", &n, &m);
	memset(h, -1, sizeof h);

	for (int i = 0; i < m; i++) {
		int a, b;
		scanf("%d%d", &a, &b);
		add(a, b); dout[a]++; din[b]++;
		if (type == 1) { add(b, a); }
	}

	if (type == 1) {
		for (int i = 1; i <= n; i++) {
			if ((din[i] + dout[i]) % 2 != 0) {
				cout << "NO" << endl; return 0;
			}
		}
	}
	else {
		for (int i = 1; i <= n; i++) {
			if (din[i] != dout[i]) {
				cout << "NO" << endl; return 0;
			}
		}
	}

	for (int i = 1; i <= n; i++) {
		if (h[i] != -1) {
			euler(i); break;
		}
	}

	if (cnt != m) {
		cout << "NO" << endl; return 0;
	}

	cout << "YES" << endl;
	for (int i = cnt; i; i--) printf("%d ", ans[i]);
	cout << endl;


	return 0;
}

dfs版本

// 欧拉模版.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

/*
* https://loj.ac/p/10105
有一天一位灵魂画师画了一张图,现在要你找出欧拉回路,即在图中找一个环使得每条边都在环上出现恰好一次。

一共两个子任务:

这张图是无向图。(50 分)

这张图是有向图。(50 分)

输入格式
第一行一个整数 t,表示子任务编号。t \in \{1, 2\},如果 t = 1 则表示处理无向图的情况,如果 t = 2 则表示处理有向图的情况。

第二行两个整数 n, m,表示图的结点数和边数。

接下来 m 行中,第 i 行两个整数 v_i, u_i,表示第 i 条边(从 1 开始编号)。保证 1 \leq v_i, u_i \leq n。

如果 t = 1 则表示 v_i 到 u_i 有一条无向边。

如果 t = 2 则表示 v_i 到 u_i 有一条有向边。

图中可能有重边也可能有自环。

输出格式
如果不可以一笔画,输出一行 NO。

否则,输出一行 YES,接下来一行输出一组方案。

如果 t = 1,输出 m 个整数 p_1, p_2, ~~~~~~, p_m。令 e = \lvert p_i \rvert,那么 e 表示经过的第 i 条边的编号。如果 p_i 为正数表示从 v_e 走到 u_e,否则表示从 u_e 走到 v_e。

如果 t = 2,输出 m 个整数 p_1, p_2, ~~~~~~, p_m。其中 p_i 表示经过的第 i 条边的编号。


1
3 3
1 2
2 3
1 3

YES
1 2 -3



2
5 6
2 3
2 5
3 4
1 2
4 2
5 1

YES
4 1 3 5 2 6


数据范围与提示
1<=n<=10^5 0<=m<=2*10^5
*/
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <cstring>

using namespace std;

const int N = 100010, M = 400010;
int h[N], e[M], ne[M], idx;
int n, m; int type;
int din[N], dout[N];
int cnt; int ans[M];
int used[M];


void add(int a, int b) {
	e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}

void dfs(int u) {
	for (int& i = h[u]; i != -1; ) {
		if (used[i]) {
			i = ne[i];
			continue;
		}
		used[i] = 1;
		if (type == 1) used[i ^ 1] = true;
		int t;
		if (type == 1) {
			t = i / 2 + 1;
			if (i % 2 == 1) { t = -t; }
		}
		else {
			t = i + 1;
		}
		int j = e[i];
		i = ne[i];
		dfs(j);

		ans[++cnt] = t;
	}
}


int main()
{
	scanf("%d",&type);
	scanf("%d%d",&n,&m);
	memset(h, -1, sizeof h);

	for (int i = 0; i < m; i++) {
		int a, b; 
		scanf("%d%d",&a,&b);
		add(a, b); dout[a]++; din[b]++;
		if (type == 1) { add(b, a); }
	}

	if (type == 1) {
		for (int i = 1; i <= n; i++) {
			if ((din[i] + dout[i]) % 2 != 0) {
				cout << "NO" << endl; return 0;
			}
		}
	}
	else {
		for (int i = 1; i <= n; i++) {
			if (din[i] != dout[i]) {
				cout << "NO" << endl; return 0;
			}
		}
	}

	for (int i = 1; i <= n; i++) {
		if (h[i] != -1) {
			dfs(i); break;
		}
	}
	if (cnt != m) {
		cout << "NO" << endl; return 0;
	}

	cout << "YES" << endl;
	for (int i = cnt; i; i--) printf("%d ",ans[i]);
	cout << endl;

	return 0;
}

标签:表示,idx,int,模版,ne,dfs,++,type,stack
From: https://www.cnblogs.com/itdef/p/18369935

相关文章

  • LeetCode-Python-3154. 到达第 K 级台阶的方案数(DFS + 数学)
    给你有一个 非负 整数 k 。有一个无限长度的台阶,最低 一层编号为0。Alice 有一个整数 jump ,一开始值为0。Alice从台阶1开始,可以使用 任意 次操作,目标是到达第 k 级台阶。假设Alice位于台阶 i ,一次 操作 中,Alice可以:向下走一级到 i-1 ,但该操作......
  • 《安富莱嵌入式周报》第341期:Stack Overflow调查报告分享开发者年薪情况,开源USB高速分
    周报汇总地址:http://www.armbbs.cn/forum.php?mod=forumdisplay&fid=12&filter=typeid&typeid=104视频版:https://www.bilibili.com/video/BV1Gw4m1k7jw目录:1、开源多功能USB2.0高速分析仪2、开源100W微型无刷伺服电机控制器3、MicroChip新款DSC系单片机集成40Msps12bitAD......
  • 【第66课】Java安全&SPEL表达式&SSTI模版注入&XXE&JDBC&MyBatis注入
    免责声明本文发布的工具和脚本,仅用作测试和学习研究,禁止用于商业用途,不能保证其合法性,准确性,完整性和有效性,请根据情况自行判断。如果任何单位或个人认为该项目的脚本可能涉嫌侵犯其权利,则应及时通知并提供身份证明,所有权证明,我们将在收到认证文件后删除相关内容。文中所涉......
  • 博客模版
    第1篇FinalShell工具的使用1.介绍xshell作为Linux远程连接的工具,教程请看《通过xshell远程连接ubuntu》。但是,xshell是付费软件。于是,找到一个finalshell作为其替换软件。FinalShell是一体化的的服务器,网络管理软件,不仅是ssh客户端,还是功能强大的开发,运维工具,充分满足开......
  • mobx模版(增删改查)
     /**@Author:Simoon.jia*@Date:2024-04-0911:06:16*@LastEditors:Simoon.jia*@LastEditTime:2024-07-2216:59:57*@Description:描述*/import{observable,action,runInAction}from'mobx';import{fetchDictionaryList,fetchd......
  • torch.stack 堆叠函数帮助理解多维数组
    概论在PyTorch中,torch.stack函数用于在指定的维度上将一组张量堆叠起来。这个操作会在指定维度上创建一个新的维度,并将输入张量在该维度上进行堆叠。假设有两个形状相同的张量a和b,它们的形状都是(2,3,4),那么在不同的dim参数下使用torch.stack会产生不同的结果。以......
  • (nice!!!)LeetCode 552. 学生出勤记录 II(动态规划dp递归版、记忆化dfs)
    题目:552.学生出勤记录II思路:记忆化搜索dfs,细节看注释classSolution{public:constintmod=1e9+7;//状态f[u][a][b]表示:在选择第u个位置前,缺勤次数为a次,且当前连续迟到次数为b次时,可以得到的合法出勤次数intf[100010][5][5];intdfs(intu,int......
  • HarmonyOS 层叠布局:(Stack)打造灵活多变的UI界面
    在应用开发中,布局设计是用户体验的关键之一。而在HarmonyOS中,层叠布局(Stack)是一种极为灵活的布局方式。它允许我们在同一个区域内放置多个组件,并根据需求将它们叠加起来,形成丰富的视觉效果。无论是广告展示还是卡片叠加效果,层叠布局都能轻松胜任。今天,我将带大家深入了解Stack......
  • 彼岸花开C++,模版初阶
    欢迎访问小马的博客,如果觉得小马的博客有帮助的话,记得点赞收藏加关注哦~~~  模版初阶(1)泛型编程(2)函数模版(3)类模版模版初阶(1)泛型编程如何实现一个通用的交换函数?voidSwap(int&a,int&b){inttmp=a;a=b;b=tmp;}voidSwap(double&a,do......
  • FastReport Net 自动把excel数据文件转为打印模版
    给FastReportNet报表工具补充了一个功能。自动生成模版,然后再用Designer精细调整。很方便。privatevoidbutton5_Click(objectsender,EventArgse){pReport=newReport();//实例化一个Report报表//registeralldatatablesandrelationspReport.RegisterData(ds)......