欧拉图的简易实现

3 篇文章 0 订阅
1 篇文章 0 订阅

欧拉图的简易实现

今天学习了欧拉图相关知识,感觉网路上的教程都过于繁琐(最后还是自己看源码弄懂的),在此谈谈自己对欧拉图的理解。
①欧拉图的作用:
欧拉图是为了解决经过图的各个连接图的线路问题,例如经过各点的连线方案(ps:实际上就是经过各点画一条线,线不能重叠),至于欧拉回路和欧拉通路的区别,在此不多赘述,反正实现起来都一样。
②欧拉图的实现:
实现欧拉图首先应该找一个有奇数连线的点(就是进去后无法出来的点)作为起点,如果点有两个以上,就表示没有能够实现欧拉回路的方案(划线必定重叠),如果没有也没有关系,可以选择其他点作为起点。
然后就用深搜遍历其他点,这里介绍一种最直观的方案,用stack栈对各点进行存储和维护。代码如下:

stack<int>s;
void dfs(int u){
	for(int v=1;v<=m;++v){
		if(oula[u][v]){
			oula[u][v]--;
			oula[v][u]--;
			dfs(v);
		}
	}
	s.push(u);
}

③欧拉图经典例题:
洛谷P2731骑马修栅栏
AC代码:

#include<bits/stdc++.h>
using namespace std;
#define M 1031
int oula[M][M],point[M];
int n,m;
stack<int>s;
void dfs(int u){
	for(int v=1;v<=m;++v){
		if(oula[u][v]){
			oula[u][v]--;
			oula[v][u]--;
			dfs(v);
		}
	}
	s.push(u);
}
int main()
{	
	cin>>n;
	m=1;
	int i;
	for(i=0;i<n;++i){
		int u,v;
		cin>>u>>v;
		m=max(m,v);
		m=max(m,u);
		oula[u][v]++;
		oula[v][u]++;
		point[u]++;
		point[v]++;
	}
	int s1=1;
	for(i=1;i<=m;++i){
		if(point[i]%2==1){
			s1=i;
			break;
		}
	}
	dfs(s1);
	while(!s.empty()){
		cout<<s.top()<<endl;
		s.pop();
	}
	return 0;
}

洛谷P1341无序字母对
AC代码:

#include<bits/stdc++.h>
using namespace std;
#define M 1031
int oula[M][M],point[M];
int n;
stack<char>s;
void dfs(int u){
	for(int v=0;v<='z'-'A';++v){
		if(oula[u][v]){
			oula[u][v]--;
			oula[v][u]--;
			dfs(v);
		}
	}
	s.push(u+'A');
}
int main()
{	
	cin>>n;
	int i;
	int s1='z'-'A';
	for(i=0;i<n;++i){
		char u,v;
		cin>>u>>v;
		s1=min(s1,u-'A');
		s1=min(s1,v-'A');
		oula[u-'A'][v-'A']++;
		oula[v-'A'][u-'A']++;
		point[u-'A']++;
		point[v-'A']++;
	}
	for(i=0;i<='z'-'A';++i){
		if(point[i]%2==1){
			s1=i;
			break;
		}
	}
    int cnt=0,h=-1;//开始找点
    for(int i=0;i<='z'-'A';i++)//在找度数为奇数的点
        if(point[i]&1){
            cnt++;
            if(h==-1)h=i;
        }
    if(h==-1)//找不到奇点,就是另外找点
        for(int i=0;i<='z'-'A';i++)
            if(point[i]){h=i;break;}
    
    if(cnt&&cnt!=2){
    	cout<<"No Solution";
    	return 0;
    }	
	dfs(h);
	if(s.size()<n+1){
		cout<<"No Solution";
		return 0;
	}
	while(!s.empty()){
		cout<<s.top();
		s.pop();
	}
	cout<<endl;
	return 0;
}

完结撒花!又水了一篇博客,嘻嘻

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

某六十九岁合法萝莉

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值