• 2018杭电多校第二场1003(DFS,欧拉回路)


    #include<bits/stdc++.h>
    using namespace std;
    int n,m;
    int x,y;
    int num,cnt;
    int degree[100007],vis[100007],viss[400040],first[100007];
    vector<int>jidian,road[100007];
    struct node
    {
        int v,next;
    }xu[400040];
    void init()//初始化
    {
        num=0,cnt=1;
        memset(degree,0,sizeof(degree));
        memset(vis,0,sizeof(vis));
        memset(viss,0,sizeof(viss));
        memset(first,-1,sizeof(first));
        jidian.clear();
    }
    void add_edge(int u,int v)//将点联接
    {
       xu[++cnt].v=v;
       xu[cnt].next=first[u];
       first[u]=cnt;
    }
    void dfs(int u)//寻找度数为奇数的点
    {
        vis[u]=1;
        if(degree[u]&1)
            jidian.push_back(u);
        for(int i=first[u];i!=-1;i=xu[i].next)
        {
            int v=xu[i].v;
            if(!vis[v])
                dfs(v);
        }
    }
    void dfss(int u)//将要走的点存进向量,绘制路线
    {
        for(int i=first[u];i!=-1;i=xu[i].next)
        {
            if(!viss[i])
            {
                viss[i]=viss[i^1]=1;//与1异或可以得到相邻的点,如:(1,2),(3,4)等
                int v=xu[i].v;
                dfss(v);
                if(i>2*m+1)//该点为奇点
                {
                    num++;//增加一笔
                }
                else
                {
                    int jiedian=i&1?(i/2):((-1)*(i/2));//如果是偶数的话,当时建边是是反向边
                    road[num].push_back(jiedian);
                }
            }
        }
    }
    int main()
    {
        while(~scanf("%d%d",&n,&m))
        {
            init();
            for(int i=1;i<=m;i++)
            {
                scanf("%d%d",&x,&y);
                add_edge(x,y);//建边
                add_edge(y,x);
                degree[x]++;//记录节点度数
                degree[y]++;
            }
            for(int i=1;i<=n;i++)
            {
                if(!vis[i]&&degree[i])//没有被访问过并且不是孤立的节点
                {
                    dfs(i);
                    int siz=jidian.size();//度数为奇数的数量
                    for(int j=2;j<siz;j+=2)//跳过欧拉回路中至少存在的两个奇点
                    {
                        add_edge(jidian[j],jidian[j+1]);
                        add_edge(jidian[j+1],jidian[j]);
                    }
                    num++;
                    if(jidian.size())
                        dfss(jidian[0]);//从多余的奇点出发
                    else
                        dfss(i);//否则就从随意一个点出发
                    jidian.clear();
                }
            }
            printf("%d ",num);
            for(int i=1;i<=num;i++)
            {
                int sizz=road[i].size();
                printf("%d ",sizz);
                for(int j=0;j<sizz-1;j++)
                {
                    printf("%d ",road[i][j]);
                }
                printf("%d ",road[i][sizz-1]);
                road[i].clear();
            }
        }
        return 0;
    }
    /*欧拉图:图中只有两个度数为奇数的点,或者所有点的度数均为偶数,
    这样我们只要选择一个度数为奇数的点作为起点跑一遍欧拉回路同时记录路径即可
    (如果所有点的度数都是偶数的话就选任意一个点就行了),
    我们dfs求完欧拉路径,然后遇到虚边,num++,
    放入另外的一个队列中(相当于上图右边切断虚边,变成了两段,最后输出所有路径方案*/

    保持热爱 不懈努力 不试试看怎么知道会失败呢(划掉) 世上无难事 只要肯放弃(划掉)
  • 相关阅读:
    ps入门
    ls命名 | Linux统计文件夹内的文件个数
    python打包成可执行文件
    装饰器
    poj 2752 Seek the Name, Seek the Fame
    字符串最大值
    次小生成树
    Selecting Courses
    poj 3461 Oulipo
    poj 2406 Power Strings
  • 原文地址:https://www.cnblogs.com/ldudxy/p/9522913.html
Copyright © 2020-2023  润新知