Fleury算法求欧拉路径 hiho第50周

题目链接:  hiho一下 第五十周 

思路:hiho已经讲的非常好了,我就不插嘴了。

提示:因为建边时同一条边同相反相的编号相近,比如(u-v)正向边u->v标号为0,反向边v->u标号为1,而0或1除以2都等于0,所以无论正反向建边,只要访问过正向反向中的任何一条边都可以用head[u]/2把原边标记为vis=1操作

/**************************************************************
    Problem:hiho 50
    User: youmi
    Language: C++
    Result: Accepted
    Time:3ms    
    Memory:0MB
****************************************************************/
//#pragma comment(linker, "/STACK:1024000000,1024000000")
//#include<bits/stdc++.h>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>
#include <stack>
#include <sstream>
#include <cmath>
#include <queue>
#include <string>
#include <vector>
#define zeros(a) memset(a,0,sizeof(a))
#define ones(a) memset(a,-1,sizeof(a))
#define sc(a) scanf("%d",&a)
#define sc2(a,b) scanf("%d%d",&a,&b)
#define rep0(i,n) for(int i=0;i<n;i++)
#define rep1(i,n) for(int i=1;i<=n;i++)
#define pt(a) printf("%d\n",a)
#define lson (step<<1)
#define rson (lson+1)
#define esp 1e-6
#define oo 0x3fffffff
#define TEST cout<<"*************************"<<endl

using namespace std;
typedef long long ll;

int n,m;

const int maxn=1000+10;
const int maxm=5000+10;
int head[maxn],euler[maxm],vis[maxn],deg[maxm<<1];//因为输出m+1个点,所以euler的大小应该为maxm
int tot,T;
struct side
{
    int v,next;
}e[maxm<<1];
void build(int u,int v)
{
    e[T].v=v;
    e[T].next=head[u];
    head[u]=T++;
}

void init()
{
    tot=0;
    T=0;
    ones(head);
    zeros(vis);
    zeros(deg);
}
void dfs(int u)
{
    //pt(u);
    while(head[u]!=-1)
    {
        int v=e[head[u]].v;
        if(!vis[head[u]/2])
        {
            vis[head[u]/2]=1;//标记无向边u-v访问过
            dfs(v);
        }
        head[u]=e[head[u]].next;//删除操作
    }
    euler[++tot]=u;//记录欧拉路径
}
int main()
{
    //freopen("in.txt","r",stdin);
    while(~sc2(n,m))
    {
        init();
        int u,v;
        while(m--)
        {
            sc2(u,v);
            build(u,v);
            build(v,u);
            deg[u]++;
            deg[v]++;
        }
        int flag=1;
        rep1(i,n)//查找度为奇数的点,如果都为偶数,那么随便从哪个点开始dfs都一样
        {
            if(deg[i]%2)
            {
                flag=i;
                break;
            }
        }
        dfs(flag);
        rep1(i,tot)
        {
            printf("%d ",euler[i]);
        }
        printf("\n");//其实这句加不加都一样,对输出要求相当宽松
    }
    return 0;
}

 

你可能感兴趣的:(算法)