HDU 1878 欧拉回路(DFS)

来源:互联网 发布:centos 7 smtp 编辑:程序博客网 时间:2024/05/17 09:14
<span style="font-family: Arial, Helvetica, sans-serif;">#include<stdio.h></span>
#include<string.h>using namespace std;int maps[1005][1005];int in[1005];int book[1005];int n,m;int dfs(int a){    book[a]=1;    for(int i=1;i<=n;i++)    {        if(book[i]==0&&maps[a][i]==1)        {            dfs(i);        }    }}int main(){    while(~scanf("%d",&n))    {        if(n==0)    return 0;        scanf("%d",&m);        memset(maps,0,sizeof(maps));        memset(in,0,sizeof(in));        memset(book,0,sizeof(book));        for(int i=0;i<m;i++)        {            int a,b;    scanf("%d%d",&a,&b);            in[a]++;    in[b]++;            maps[a][b]=maps[b][a]=1;        }        dfs(1);        int flag=1;        for(int i=1;i<=n;i++)        {            if(in[i]%2==1||book[i]==0)            {                flag=0;            }        }        if(flag==0)        {            printf("0\n");        }        else        {            printf("1\n");        }    }}

算法思想:

判断一个图中是否存在欧拉回路(每条边恰好只走一次,并能回到出发点的路径),在以下三种情况中有三种不同的算法:

一、无向图
每个顶点的度数都是偶数,则存在欧拉回路。

 

二、有向图(所有边都是单向的)
每个节顶点的入度都等于出度,则存在欧拉回路。

以上两种情况都很好理解。其原理就是每个顶点都要能进去多少次就能出来多少次。

 

三、混合图(有的边是单向的,有的边是无向的。常被用于比喻城市里的交通网络,有的路是单行道,有的路是双行道。)
找到一个给每条无向的边定向的策略,使得每个顶点的入度等于出度,这样就能转换成上面第二种情况。这就可以转化成一个二部图最大匹配问题。网络模型如下:

1. 新建一个图。
2. 对于原图中每一条无向边i,在新图中建一个顶点e(i);
3. 对于原图中每一个顶点j,在新图中建一个顶点v(j)。
4. 如果在原图中,顶点j和k之间有一条无向边i,那么在新图中从e(i)出发,添加两条边,分别连向v(j)和v(k),容量都是1。
5. 在新图中,从源点向所有e(i)都连一条容量为1的边。
6. 对于原图中每一个顶点j,它原本都有一个入度in、出度out和无向度un。显然我们的目的是要把所有无向度都变成入度或出度,从而使它的入度等于总度数的一半,也就是(in + out + un) / 2(显然与此同时出度也是总度数的一半,如果总度数是偶数的话)。当然,如果in已经大于总度数的一半,或者总度数是奇数,那么欧拉回路肯定不存大。如果in小于总度数的一半,并且总度数是偶数,那么我们在新图中从v(j)到汇点连一条边,容量就是(in + out + un) / 2 – in,也就是原图中顶点j还需要多少入度。

按照这个网络模型算出一个最大流,如果每条从v(j)到汇点的边都达到满流量的话,那么欧拉回路成立。

 

 

欧拉回路一定要联通的


欧拉回路(这个题居然就叫欧拉回路)
Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u
Submit Status

Description

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

Input

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

Output

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

Sample Input

3 31 21 32 33 21 22 30

Sample Output

10

0 0
原创粉丝点击