星际旅行(思维很好的欧拉路)

本文探讨了欧拉路径与回路的概念,详细分析了如何通过修改图结构来确保存在欧拉路径,同时介绍了判断图联通性的独特算法。通过对每条边的拆分和自环的处理,提出了寻找特定条件下航线的解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

把每条边拆成两条。欧拉(回)路,只有0或2两个奇点。因为2条边经过一次,m-2条边经过两次,可以考虑删除两条边,使剩下的图有0或2两个奇点。所以这两条边要么是任意两个自环,要么是有一个公共端点的两条边,要么是一个自环和任意一条边。

我们要判断,整个图联不联通,因为要经过m条边。然而我们判断所有边联通的点联不联通,不是判断所有点联不联通。如下图,所有点不联通,但是能找到航线。

#include<bits/stdc++.h>
using namespace std;
long long fa[1000010], n, m, ru[1000010], zuo[1000010], you[1000010], si;
int find(int x)
{
	if(x == fa[x]) return x;
	return fa[x] = find(fa[x]);
}
void  unio(int x,int y)
{
	int r1 = find(x); int r2 = find(y); fa[r1] = r2;
}
int main()
{
	scanf("%lld%lld",&n,&m);
	for(int i = 1; i <= n; i++) fa[i] = i;
	for(int i = 1; i <= m; i++)
	{
	 scanf("%d%d",&zuo[i],&you[i]);
		if(zuo[i]!= you[i]){
		unio(zuo[i],you[i]);ru[you[i]]++;	ru[zuo[i]]++;
		}else si++;
	}
	int ha = find(zuo[1]);
	for(int i = 2; i <= m; i++)
	{
		int he = find(zuo[i]);
		if(ha  != he) {
			printf("0"); return 0;
		}
	}
	long long ans = 0;
	ans = si * (si-1);
	ans += si * (m - si);
	for(int i = 1; i <= n; i++)
	ans += ru[i] * (ru[i] - 1)/2;
	cout << ans;
	return 0;
} 

 

### 关于欧拉路的概念 在图论中,欧拉通路是指通过图中所有边恰好一次且行遍所有顶点的通路[^2]。对于无向图而言,如果该图连通,并且恰有两个节点的度数为奇数,其余节点的度数均为偶数,则此图存在欧拉通路[^3]。 #### 判定条件 - **无向图中的欧拉通路**:若一个无向图中有且仅有两个顶点的度数为奇数,那么这个图就一定存在一条从其中一个奇数度顶点到另一个奇数度顶点之间的欧拉通路。 - **有向图中的欧拉通路**:在一个强联通分量内,若有且仅有一对顶点满足入度减去出度等于±1的关系,即存在一对特殊的起点和终点使得整个图形能够形成单次访问每条弧线的一趟旅程[^4]。 #### 实现方法 为了找到这样的路径,通常采用深度优先搜索(DFS)的方法来实现: ```cpp #include <iostream> #include <vector> using namespace std; void dfs(int u, vector<vector<int>>& adjList, vector<bool>& visitedEdges, stack<int>& path){ for (int& v : adjList[u]){ if (!visitedEdges[v]) { visitedEdges[v] = true; dfs(v ^ 1, adjList, visitedEdges, path); } } path.push(u); } bool findEulerPath(vector<pair<int,int>> edges, int nVertices, vector<int>& result){ // 构建邻接表并统计各点度数 vector<vector<int>> adjList(edges.size() * 2 + 1); vector<int> degree(nVertices + 1); for (size_t i = 0; i < edges.size(); ++i){ auto [u,v] = edges[i]; adjList[u].push_back(i*2+1); adjList[v].push_back(i*2); degree[u]++; degree[v]++; } // 记录起始位置以及判断是否存在合法解 int startVertex = -1, oddDegreeCount = 0; for (int i = 1; i <= nVertices && oddDegreeCount <= 2; ++i){ if(degree[i]%2==1){ startVertex=startVertex==-1?i:startVertex; oddDegreeCount++; }else if(startVertex==-1&&degree[i]>0){startVertex=i;} } if ((oddDegreeCount != 0 && oddDegreeCount != 2)) return false; // 初始化辅助数据结构 vector<bool> visitedEdges(adjList.size(),false); stack<int> path; // 执行深搜构建路径 dfs(startVertex,adjList,visitedEdges,path); while(!path.empty()){ result.push_back(path.top()); path.pop(); } reverse(result.begin(),result.end()); return true; } ``` 这段代码实现了寻找给定简单无向图中存在的任意一条欧拉通路的功能。它首先建立了一个基于输入边列表形式表示的图模型,接着利用深度优先搜索策略探索可能存在的欧拉通路,并最终返回由这些顶点构成的结果序列。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值