• 欧拉回路,欧拉路径(收录


    介绍的内容

    博客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
  • 相关阅读:
    Java 常见关键字总结:final、static、this、super!
    URI与URL傻傻分不清楚?
    深入TLS/SSL协议
    排球计分软件功能(记分员计分功能)
    观《罗辑思维之怎样成为一个高手》有感
    个人项目制作(PSP)
    计应152班第3小组之软件初步开发(小组项目)
    本周个人总结
    本周个人总结(软件的初步开发)
    计应152班第3小组之软件初步开发(小组项目)
  • 原文地址:https://www.cnblogs.com/thunder-110/p/10326696.html
Copyright © 2020-2023  润新知