欧拉图的简易实现
今天学习了欧拉图相关知识,感觉网路上的教程都过于繁琐(最后还是自己看源码弄懂的),在此谈谈自己对欧拉图的理解。
①欧拉图的作用:
欧拉图是为了解决经过图的各个连接图的线路问题,例如经过各点的连线方案(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;
}
完结撒花!又水了一篇博客,嘻嘻