zoukankan      html  css  js  c++  java
  • 欧拉回路,欧拉路径(收录

    介绍的内容

    博客2

    题目:欧拉回路

    题意:

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

    #include<iostream>
    #include<cstdio>
    #include <cctype>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<string>
    #include<cmath>
    #include<set>
    #include<vector>
    #include<stack>
    #include<queue>
    #include<map>
    using namespace std;
    #define ll long long
    #define mem(a,x) memset(a,x,sizeof(a))
    #define se second
    #define fi first
    const ll mod=998244353;
    const int INF= 0x3f3f3f3f;
    const int N=2e5+5;
    
    int n,m;
    int du[1005];
    int f[1005];
    
    int getf(int x)
    {
        if(x!=f[x])
        {
            f[x]=getf(f[x]);
        }
        return f[x];
    }
    int main()
    {
        int a,b,fa,fb;
        while(cin>>n && n)
        {
            cin>>m;
            int cnt=0;
            mem(f,0);
            mem(du,0);
            for(int i=0;i<=n;i++) f[i]=i;
            while(m--)
            {
                cin>>a>>b;
                du[a]++; du[b]++;
                fa=getf(a);
                fb=getf(b);
                if(fa!=fb) 
                {
                    f[fa]=fb;
                }
                else cnt++; 
                //如果fa==fb,则两个节点在同一并查集中, 
                //这样的情况有且只能出现一次 ,否则走的路径会存在重复 
            }
            if(cnt!=1)
            {
                cout<<0<<endl; continue;
            }
            int flag=0;
            for(int i=1;i<=n;i++)
            {
                if(du[i]%2!=0){
                    flag=1; break;
                }
            }
            cout<< (flag? 0:1)<<endl;
        } 
    }
    并查集判断欧拉回路

    题目:Watchcow

    参考博客

    题意:

      求无向图每条边恰好经过两次,在回到原点,输出经过的顶点。容易转化为有向图欧拉回路每条边经过一次。

    #include<iostream>
    #include<cstdio>
    #include <cctype>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<string>
    #include<cmath>
    #include<set>
    #include<vector>
    #include<stack>
    #include<queue>
    #include<map>
    using namespace std;
    #define ll long long
    #define mem(a,x) memset(a,x,sizeof(a))
    #define se second
    #define fi first
    const ll mod=998244353;
    const int INF= 0x3f3f3f3f;
    const int N=2e5+5;
    
    int n,m,cnt=0;
    int ans[200005];
    struct edge
    {
        int to,flag;
        edge(int _to,int _flag):to(_to),flag(_flag){}
    };
    vector<edge> v[200005];
    
    void dfs(int x)
    {
        for(int i=0;i<v[x].size();i++)
        {
            if(v[x][i].flag==0)
            {
                
                v[x][i].flag=1;
                dfs(v[x][i].to);
            }
            
        }
        ans[++cnt]=x;
    } 
    
    int main()
    {
        int a,b;
        cin>>n>>m;
        while(m--)
        {
            scanf("%d%d",&a,&b);
            v[a].push_back(edge(b,0));
            v[b].push_back(edge(a,0));
        }
        dfs(1);
        //printf("1
    ");
        for(int i=1;i<=cnt;i++)
            printf("%d
    ",ans[i]);
        return 0;
    }
    欧拉回路 路径打印

    题目:Ant Trip

    参考博客   证明可见

    题意:

      给你无向图的N个点和M条边,保证这M条边都不同且不会存在同一点的自环边,现在问你至少要几笔才能所有边都画一遍.(一笔画的时候笔不离开纸)

    思路:

      (1)如果该连通分量是一个孤立的点,即num[i]==0或num[i]==1的时候,注意num[i]==0表示i不是根节点,num[i]==1表示的是独立的点。

      (2)如果该连通分量是欧拉图或半欧拉图,那么只需要1笔即可,即num[i]>1且sum[i]==0的时候,表示是(半)欧拉图。

      (3)如果该连通分量不是一个欧拉图时,那么我们需要奇数度点个数/2,即num[i]>1且sum[i]>0时需要sum[i]/2笔。

    #include<iostream>
    #include<cstdio>
    #include <cctype>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<string>
    #include<cmath>
    #include<set>
    #include<vector>
    #include<stack>
    #include<queue>
    #include<map>
    using namespace std;
    #define ll long long
    #define mem(a,x) memset(a,x,sizeof(a))
    #define se second
    #define fi first
    const ll mod=998244353;
    const int INF= 0x3f3f3f3f;
    const int N=2e5+5;
    
    int n,m;
    int du[N],f[N],num[N],sum[N]; 
    //num[i]表示祖宗节点为i的并查集内有多少个节点 
    //sum[i]表示祖宗节点为i的并查集内 度数为奇数的节点数量 
    
    int getf(int x)
    {
        if(x!=f[x])
        {
            f[x]=getf(f[x]);
        }
        return f[x];
    }
    
    
    int main()
    {
        int a,b,fa,fb,cnt;
        while(cin>>n>>m)
        {
            mem(f,0);
            mem(du,0);
            mem(num,0);
            mem(sum,0);
            int ans=0;
            for(int i=0;i<=n;i++) f[i]=i;
            
            for(int i=1;i<=m;i++)
            {
                   cin>>a>>b;
                du[a]++; du[b]++;
                fa=getf(a); fb=getf(b);
                if(fa!=fb) f[fa]=fb;
            }
    
            for(int i=1;i<=n;i++)
            {
                num[getf(i)]++;
                if(du[i]&1)
                    sum[getf(i)]++;
            }
            for(int i=1;i<=n;i++)
            {
                if(num[i]==0 || num[i]==1) continue; //表示节点i是孤立的 
                
                if(sum[i]>0)
                    ans+=sum[i]/2;
                else if(sum[i]==0)
                    ans++;
            }
            cout<<ans<<endl;
        } 
    }
    View Code
  • 相关阅读:
    mac上python3安装HTMLTestRunner
    双目深度估计传统算法流程及OpenCV的编译注意事项
    深度学习梯度反向传播出现Nan值的原因归类
    1394. Find Lucky Integer in an Array
    1399. Count Largest Group
    1200. Minimum Absolute Difference
    999. Available Captures for Rook
    509. Fibonacci Number
    1160. Find Words That Can Be Formed by Characters
    1122. Relative Sort Array
  • 原文地址:https://www.cnblogs.com/thunder-110/p/10326696.html
Copyright © 2011-2022 走看看