hdu-1878欧拉回路

欧拉回路

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 13320    Accepted Submission(s): 4972


Problem Description
欧拉回路是指不令笔离开纸面,可画过图中每条边仅一次,且可以回到起点的一条回路。现给定一个图,问是否存在欧拉回路?
 

Input
测试输入包含若干测试用例。每个测试用例的第1行给出两个正整数,分别是节点数N ( 1 < N < 1000 )和边数M;随后的M行对应M条边,每行给出一对正整数,分别是该条边直接连通的两个节点的编号(节点从1到N编号)。当N为0时输入结
束。
 

Output
每个测试用例的输出占一行,若欧拉回路存在则输出1,否则输出0。
 

Sample Input
  
  
3 3 1 2 1 3 2 3 3 2 1 2 2 3 0
 

Sample Output
  
  
1 0
 

Author
ZJU
 

Source
 
假设5 个顶点,10条边

起始顶点             1           2            3          4           5          

起始父节点         1           2            3          4           5          

1---2  

1---3

1---4

1---5

2---3

2---4

3---5

4---5

1.并查集

若为欧拉图,相当于图中所有顶点都相连(类比最小生成树),所以除了根节点以外,每个顶点都指向其他顶点(最终都指向跟节点)

欧拉图顶点        1                           2                         3                 4                   5              

父节点             2(!1)            3(!2)               4(!3)              5(!4)               5

这里假设顶点6是根节点    

 

判断一个图是否为欧拉回路充要条件是 判断图中所有顶点的度是否都为偶数,还需判断是否为联通图。 判断联通图方法为并查集,这里使用最简单的并查集

#include<iostream>
#include<cstring>
#include<queue>
#include<algorithm>
#include<cstdlib>
#include<cstdio>
using namespace std;
#define INF 0x3f3f3f3f
const int MaxV = 1005;
int degree[MaxV],fa[MaxV];//分别表示顶点的度数和顶点的父节点,就是指向该点的顶点
int N,M;
int find(int x)//获取根节点
{
    return fa[x]==x?x:find(fa[x]);
}
int main(){
    while(scanf("%d",&N)){
        if(N==0)break;
        scanf("%d",&M);
        memset(degree,0,sizeof(degree));//初始所有节点的度为0
        for(int i = 1 ; i <= N; i++)
            fa[i] = i ;                 //所有结点的父节点都是自身
        for(int i = 0 ; i < M ; i ++){
            int u,v;
            scanf("%d%d",&u,&v);
            degree[u]++;                 //无向图,出度+1
            degree[v]++;                   //入度+1
            int x = find(fa[u]);
            int y = find(fa[v]);
            if(x!=y) //判断输入的两个顶点是否属于同一个树,即是否联通
                fa[x]=y;       //如果不联通,将其联通
        }
        bool t1=false,t2=true ;
        int cnt = 0 ;
        for(int i = 1 ; i <= N ; i++){
            if(fa[i] == i )     //判断所有顶点是否联通,若联通说明每个顶点的父节点都为某个顶点
                cnt++;        //也就是说所有顶点中只有一个顶点与父节点相同
            if(degree[i]&1){    //判断每个顶点的度数是否为奇数,一旦是,则证明不是欧拉图
                t2 = false ;
                break;
            }
        }
        if (cnt == 1)
            t1= true;
        if(t1 && t2 )printf("1\n");//两个条件同时成立说明为欧拉图
        else printf("0\n");
    }
	return 0;
}


2 .dfs

#include<iostream>
#include<cstring>
#include<queue>
#include<algorithm>
#include<cstdlib>
#include<vector>
#include<cstdio>
using namespace std;
#define INF 0x3f3f3f3f
const int MaxV = 1005;
int vis[MaxV];
vector<int>vec[MaxV];
int N,M;
void dfs(int i ){
    vis[i] = 1;
    vector<int>::iterator it;
    for(it = vec[i].begin() ; it!=vec[i].end(); it++){
        if(vis[*it] == 0)
            dfs(*it);
    }
}
int main(){
    while(scanf("%d",&N)){
        if(N==0)break;
        scanf("%d",&M);
        memset(vis,0,sizeof(vis));
        for(int i = 1 ; i <= N; i++)
            vec[i].clear();
        for(int i = 0 ; i < M ; i ++){
            int u,v;
            scanf("%d%d",&u,&v);
            vec[u].push_back(v);
            vec[v].push_back(u);
        }
        dfs(1);

        int cnt = 0 ;
        bool t1 = false ,t2 = true;
        for(int i = 1 ; i <= N ; i++){
            if(!vis[i])
                cnt++;
            if(vec[i].size()&1){
                t2 = false ;
            }
        }
        if (!cnt)
            t1= true;
        if(t1 && t2 )printf("1\n");//两个条件同时成立说明为欧拉图
        else printf("0\n");
    }
	return 0;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值