算法复习——欧拉回路(uoj117)

题目:

题解:

  欧拉回路相关定理(相关定义和证明请参见其他资料):

  1.欧拉回路

    (1)有向图:所有点的出度都等于入度为该图为欧拉图(存在欧拉回路)的充要条件。

    (2)无向图:所有点的度都为偶数为该图为欧拉图(存在欧拉回路)的充要条件。

  2.欧拉通路

    (1)有向图:除两点(其中一点出度+1==入度,另一点入度+1==出度)另外点出度都等于入度为该图为半欧拉图(存在欧拉通路)的充要条件。

    (2)无向图:除两点(两点度都为奇数)另外点的度都为偶数为该图为半欧拉图(存在欧拉通路)的充要条件。

  以上定理用于判断是否为存在欧拉回路或者通路

  接下来是两个推论:

  

 

  

  嗯就是这样··再回到这道题上,一道很裸地模版题···然而被uoj大佬的数据教做人··

  注意判定重边不然就会超时·····用类似于网络流的cur来优化(具体见代码)

代码:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<ctime>
#include<cctype>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
const int N=1e5+5;
const int M=5e5+5;
int first[N],go[M*2],next[M*2],tot=0;
int n,m,T,ru[N],chu[N],stack[M*2],cnt;
bool visit[M];
inline void comb(int a,int b)
{
  next[++tot]=first[a],first[a]=tot,go[tot]=b;
}
inline void dfs1(int u)
{
  for(int &e=first[u];e;e=next[e])
  {
    if(!visit[e])
    {
      visit[e]=true;
      if(e%2==1)
        visit[e+1]=true;
      else
        visit[e-1]=true;
      int t=e;
      dfs1(go[e]);
      stack[++cnt]=t;
    }
  }
}
inline void dfs2(int u)
{
  for(int &e=first[u];e;e=next[e])
  {
    if(!visit[e])
    {
      visit[e]=true;
      int t=e;
      dfs2(go[e]);
      stack[++cnt]=t;
    }
  }
}
int main()
{
  //freopen("a.in","r",stdin);
  scanf("%d",&T);
  int a,b;
  scanf("%d%d",&n,&m);
  if(T==1)  //无向图情况 
  { 
    for(int i=1;i<=m;i++)
    {
      scanf("%d%d",&a,&b);
      comb(a,b);
      comb(b,a);
      ru[b]++;
      chu[a]++;
    }
    for(int i=1;i<=n;i++)
      if((ru[i]+chu[i])%2==1)
      {
        cout<<"NO"<<endl;
        return 0;
      }
    for(int i=1;i<=n;i++)
    {
      if(first[i])
      {  
        dfs1(i);
        break;
      }
    }
    if(cnt!=m)  
    {  
      cout<<"NO"<<endl;
      return 0;
    }
    cout<<"YES"<<endl;
    for(int i=cnt;i>=1;i--)
    {  
      if(stack[i]%2==1)
        cout<<(stack[i]+1)/2<<" ";
      else
        cout<<stack[i]/2*(-1)<<" ";
    }
    return 0;
  }
  else
  {
    for(int i=1;i<=m;i++)
    {
      scanf("%d%d",&a,&b);
      comb(a,b);
      ru[b]++;
      chu[a]++;
    }
    for(int i=1;i<=n;i++)
      if(ru[i]!=chu[i])
      {
        cout<<"NO"<<endl;
        return 0;
      }
     for(int i=1;i<=n;i++)
     {
       if(first[i])
       {  
         dfs2(i);
         break;
       }
     }
    if(cnt!=m)  
    {  
      cout<<"NO"<<endl;
      return 0;
    }
    cout<<"YES"<<endl;
    for(int i=cnt;i>=1;i--)
      cout<<stack[i]<<" ";
    return 0;
  }
}

 

  

 

 

posted @ 2017-09-02 17:19  AseanA  阅读(767)  评论(0编辑  收藏  举报