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

Posted ldudxy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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++,
放入另外的一个队列中(相当于上图右边切断虚边,变成了两段,最后输出所有路径方案*/















































































































以上是关于2018杭电多校第二场1003(DFS,欧拉回路)的主要内容,如果未能解决你的问题,请参考以下文章

2020杭电多校第二场题解

2022杭电多校第二场 A.Static Query on Tree(树剖)

2022杭电多校第二场 A.Static Query on Tree(树剖)

2022杭电多校第二场 A.Static Query on Tree(树剖)

2022杭电多校第二场 A.Static Query on Tree

2022杭电多校第二场 A.Static Query on Tree