HDU1878 欧拉回路

欧拉回路

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

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

Source

浙大计算机研究生复试上机考试-2008年

Recommend

We have carefully selected several similar problems for you:  1879 1880 1877 1881 1863 

若图G中存在这样一条路径,使得它恰通过G中每条边一次,则称该路径为欧拉路径。

若该路径是一个圈,则称为欧拉(Euler)回路。具有欧拉回路的图为欧拉图。

定理:

(一)一个图有欧拉回路当且仅当它是连通的且每个顶点都有偶数度。

(二)一个图有欧拉通路当且经当它是连通的且除两个顶点外,其他顶点都有偶数度。

在第二个定理下,含奇数度的两个节点中,一个必为欧拉通路起点,另一个必为欧拉通路的终点。

1.判断欧拉路是否存在的方法
有向图:图连通,有一个顶点:出度=入度+1,有一个顶点:入度=出度+1,其余都是出度=入度。
无向图:图连通,只有两个顶点是奇数度,其余都是偶数度。


2.判断欧拉回路是否存在的方法
有向图:图连通,所有的顶点出度=入度。
无向图:图连通,所有顶点都是偶数度。

用DFS判断图是否连通

#include<bits/stdc++.h>
using namespace std;
#define maxn 1005
#define inf 0x3f3f3f3f
int n,m;
vector<int> G[maxn];
bool vis[maxn];//标记节点是否遍历过
int degree[maxn];//记录节点的度
void dfs(int point)//深度优先搜索每个点
{
    vis[point]=1;//标记访问过
    for(int i=0;i<G[point].size();i++)//遍历所有与当前点相邻的点
    {
        int next=G[point][i];
        if(!vis[next])//如果没有访问过
            dfs(next);//继续访问
    }
}
int main()
{
    while(scanf("%d",&n)!=EOF&&n){
        scanf("%d",&m);
        for(int i=1;i<=n;i++)
            G[i].clear();//多组测试,一定要清空
        memset(vis,0,sizeof(vis));
        memset(degree,0,sizeof(degree));
        while(m--){
            int u,v;
            scanf("%d%d",&u,&v);
            degree[u]++;//节点度数+1
            degree[v]++;
            G[u].push_back(v);
            G[v].push_back(u);
        }
        dfs(1);
        bool flag=0;
        for(int i=1;i<=n;i++)
        if(!vis[i]){//如果存在节点没有访问过,则图不连通
            flag=1;break;
        }
 
        if(flag)
            printf("0\n");
        else{
            flag=0;
            for(int j=1;j<=n;j++)
                if(degree[j]&1)//奇数
                {//存在某个点的度数为奇数,则不是欧拉回路
                     flag=1;
                     break;
                }
            if(flag)    printf("0\n");
            else printf("1\n");
        }
    }
    return 0;
}

用并查集来判断图是否连通

#include<bits/stdc++.h>
using namespace std;
#define maxn 1005
#define inf 0x3f3f3f3f
int n,m;
int pre[maxn];//标记每个节点的前驱
int degree[maxn];//每个节点的度
int findset(int x)//寻找前驱
{
    if(pre[x]==x)
        return x;
    return pre[x]=findset(pre[x]);//压缩路径
}
void unionset(int x,int y)//合并两个连通分量
{
    int fx=findset(x),fy=findset(y);
    pre[fx]=fy;
}
int main()
{
    while(scanf("%d",&n)!=EOF&&n){
        scanf("%d",&m);
        for(int i=1;i<=n;i++)
            pre[i]=i;//初始化前驱为自己
        memset(vis,0,sizeof(vis));
        memset(degree,0,sizeof(degree));
        while(m--){
            int u,v;
            scanf("%d%d",&u,&v);
            degree[u]++;//度数+1
            degree[v]++;
            unionset(u,v);
        }
        bool flag=0;
        int father=findset(1);//根节点
 
        for(int i=2;i<=n;i++)
        if(findset(i)!=father){//存在其他根节点
            flag=1;break;//则图是不连通的
        }
 
        if(flag)
            printf("0\n");
        else{
            flag=0;
            for(int j=1;j<=n;j++)
                if(degree[j]&1)//奇数
                {
                     flag=1;
                     break;
                }
            if(flag)    printf("0\n");
            else printf("1\n");
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_40507857/article/details/81673554