题目大意:
给出无向图,判断它是Eulerian, semi-Eulerian, or non-Eulerian.
按标号顺序输出每个结点的度,第二行输出判断结果
思路:
其实这个题虽然写的是欧拉回路,但是我觉得应该不会需要我们实现这个算法,而是利用这个算法里的特性进行判断。而这个特性,在题中就有说:
- 如果所有结点的度都是偶数,就是Eulerian
- 如果除了两个结点的度是奇数其他都是偶数,就是semi-Eulerian
- 除了上面的情况,就是non-Eulerian
所以这里我们需要解决的就是求出每个结点的度进行判断。
我想到尝试用动态邻接数组来进行存储图的信息,那么每个节点的size,就是它的度。
代码:
#include<iostream>
#include<vector>
using namespace std;
int main(){
int n,m;
cin>>n>>m;
vector<int> Adj[n+1];
while(m--){
int e1,e2;
cin>>e1>>e2;
Adj[e1].push_back(e2);
Adj[e2].push_back(e1);
}
int oddnum=0;
for(int i=1;i<=n;i++){
printf("%d%s",Adj[i].size(),i==n?"\n":" ");
if(Adj[i].size()%2!=0) oddnum++;
}
if(oddnum==0) printf("Eulerian\n");
else if(oddnum==2) printf("Semi-Eulerian\n");
else printf("Non-Eulerian\n");
return 0;
}
不知道这个测试点错误的原因,所以我去欣赏了一下其他的代码,发现要考虑图的连通性。
所以在原先代码上作了修正。
#include<iostream>
#include<vector>
using namespace std;
int n,m;
vector<int> Adj[509];
bool vis[509]={false};
int cnt=0;
void dfs(int index){
vis[index]=true;
cnt++;
for(int i=0;i<Adj[index].size();i++){
if(vis[Adj[index][i]]==false) dfs(Adj[index][i]);
}
}
int main(){
cin>>n>>m;
/*if(m==0||n==1){ 把这段注释掉后就全部正确了
printf("Non-Eulerian\n");return 0;
}*/
while(m--){
int e1,e2;
cin>>e1>>e2;
Adj[e1].push_back(e2);
Adj[e2].push_back(e1);
}
int oddnum=0;
for(int i=1;i<=n;i++){
printf("%d%s",Adj[i].size(),i==n?"\n":" ");
if(Adj[i].size()%2!=0) oddnum++;
}
dfs(1);
/*if(cnt!=n){
printf("Non-Eulerian\n");
return 0;
}*/
if(oddnum==0&&cnt==n) printf("Eulerian\n");
else if(oddnum==2&&cnt==n) printf("Semi-Eulerian\n");
else printf("Non-Eulerian\n");
return 0;
}
- 只有一个顶点的图也叫欧拉图
- 欧拉图一定是连通图
- 有一些图的判断里要记得判断它的连通性(用上面的dfs函数来判断)
其实有尝试用下列代码实现连通性的检测,但一直无法通过,暂时没找到原因。
#include<iostream>
#include<vector>
using namespace std;
int n,m;
vector<int> Adj[509];
/*bool vis[509]={false};
int cnt=0;
void dfs(int index){
vis[index]=true;
cnt++;
for(int i=0;i<Adj[index].size();i++){
if(vis[Adj[index][i]]==false) dfs(Adj[index][i]);
}
}*/
int main(){
cin>>n>>m;
for(int i=0;i<m;i++){
int e1,e2;
cin>>e1>>e2;
Adj[e1].push_back(e2);
Adj[e2].push_back(e1);
}
int oddnum=0;
bool connected=true;
for(int i=1;i<=n;i++){
printf("%d%s",Adj[i].size(),i==n?"\n":" ");
if(Adj[i].size()%2!=0) oddnum++;
else if(Adj[i].size()==0) connected=false;
}
//dfs(1);
/*if(cnt!=n){
printf("Non-Eulerian\n");
return 0;
}*/
if(m==0||(oddnum==0&&connected)) printf("Eulerian\n");
else if(oddnum==2&&connected) printf("Semi-Eulerian\n");
else printf("Non-Eulerian\n");
return 0;
}