zoukankan      html  css  js  c++  java
  • UOJ 117 欧拉回路(套圈法+欧拉回路路径输出+骚操作)

    题目链接:http://uoj.ac/problem/117

    题目大意:

    解题思路:先判断度数:

         若G为有向图,欧拉回路的点的出度等于入度。

         若G为无向图,欧拉回路的点的度数位偶数。

         然后判断连通性,并且输出路径需要用套圈法(其实我也不是很懂)。

         还学了一些骚操作:

         ①用链式前向星存图,如果是有向图,那idx隔两个存一条边,如果是无向图则idx隔一个存一条边,且idx从2开始。这样写的作用就是在寻无向图路径时可以良好地标记,比如第一条无向边里idx=2、3分别对应一条正反边,2和3除2都对应1,那么我们只需标记vis[1]就好了,因为欧拉回路只需要用到其中一条边。有向图因为要防止两条当一条用,所以要idx要隔2存一条边。

         ②在遍历邻接表时j加一个引用,快了超多。

    代码:

     1 #include<iostream>
     2 #include<stack>
     3 #include<cstdio>
     4 #include<cstring>
     5 #include<algorithm>
     6 using namespace std;
     7 const int N=1e5+5;
     8 const int M=2e5+5;
     9 
    10 struct node{
    11     int to,next,w;
    12 }edge[M*2];
    13 
    14 int n,m,idx,cnt;
    15 int head[N],in_deg[N],out_deg[N],ans[N];
    16 bool vis[M*2];
    17 
    18 void init(){
    19     idx=2;
    20     memset(vis,false,sizeof(vis));
    21     memset(head,0,sizeof(head));
    22     memset(in_deg,0,sizeof(in_deg));
    23     memset(out_deg,0,sizeof(out_deg));
    24 }
    25 
    26 void addedge(int u,int v,int w){
    27     edge[idx].to=v;
    28     edge[idx].next=head[u];
    29     edge[idx].w=w;
    30     head[u]=idx++;
    31 }
    32 
    33 //传说中的套圈法,输出欧拉回路路径
    34 void dfs(int u){
    35     //这个引用好神奇啊,速度快了好多,学习了0 0
    36     //好像类似于网络流的cur优化(没学过网路流,瞎说的)
    37     //然后关于idx的处理也很巧妙
    38     for(int &j=head[u];j;j=edge[j].next){
    39         node t=edge[j];
    40         if(!vis[j>>1]){
    41             vis[j>>1]=true;
    42             dfs(t.to);
    43             ans[++cnt]=t.w;
    44         }
    45     }
    46 }
    47 
    48 int main(){
    49     int t;
    50     scanf("%d%d%d",&t,&n,&m);
    51     init();
    52     int a,b;
    53     for(int i=1;i<=m;i++){
    54         scanf("%d%d",&a,&b);
    55         addedge(a,b,i);
    56         in_deg[b]++;
    57         out_deg[a]++;
    58         if(t==1)
    59             addedge(b,a,-i);
    60         else
    61             idx++;
    62     }
    63     bool flag=true;
    64     if(t==1){
    65         for(int i=1;i<=n;i++){
    66             if((in_deg[i]+out_deg[i])%2){
    67                 flag=false;
    68                 break;
    69             }
    70         }
    71     }
    72     else{
    73         for(int i=1;i<=n;i++){
    74             if(in_deg[i]!=out_deg[i]){
    75                 flag=false;
    76                 break;
    77             }
    78         }
    79     }
    80     if(flag){
    81         dfs(a);
    82         if(cnt!=m)
    83             puts("NO");
    84         else{
    85             puts("YES");
    86             for(int i=cnt;i>=1;i--){
    87                 if(i==1)
    88                     printf("%d
    ",ans[i]);
    89                 else
    90                     printf("%d ",ans[i]);
    91             }
    92         }
    93     }
    94     else
    95         puts("NO");
    96     return 0;
    97 }
  • 相关阅读:
    两个数据库比较 对比视图存储过程及表结构差异
    导入/导出Excel
    比较两个数据库的表结构差异
    根据当月数据库自动生成下个月数据库--3
    根据当月数据库自动生成下个月数据库--2
    根据当月数据库自动生成下个月数据库--1
    ubuntu 分屏工具
    ubuntu 分屏工具
    中英文对照 —— 色彩的描述
    中英文对照 —— 色彩的描述
  • 原文地址:https://www.cnblogs.com/fu3638/p/7912579.html
Copyright © 2011-2022 走看看