zoukankan      html  css  js  c++  java
  • 【UOJ 117】欧拉回路

    #117. 欧拉回路

    有一天一位灵魂画师画了一张图,现在要你找出欧拉回路,即在图中找一个环使得每条边都在环上出现恰好一次。

    一共两个子任务:

    1. 这张图是无向图。(50分)

    输入格式

    第一行一个整数 t,表示子任务编号。t{1,2},如果 t=1则表示处理无向图的情况,如果 t=2 则表示处理有向图的情况。

    第二行两个整数 n,m,表示图的结点数和边数。

    接下来 m 行中,第 i 行两个整数 vi,ui,表示第 ii 条边(从 11 开始编号)。保证 1vi,uin

    1. 如果 t=1 
    2. 则表示 vi 到 ui 有一条无向边。
    3. 如果 t=2 
    4. 则表示 vi 到 ui 有一条有向边。

    图中可能有重边也可能有自环。

    输出格式

    如果不可以一笔画,输出一行 “NO”。

    否则,输出一行 “YES”,接下来一行输出一组方案。

    如果 t=1,输出 m个整数 p1,p2,,pm。令 e=∣pi∣,那么 e 表示经过的第 i 条边的编号。如果 pi 为正数表示从 ve 走到 ue,否则表示从 ue 走到 ve。

    如果 t=2输出 m 个整数 p1,p2,,pm。其中 pi 表示经过的第 i条边的编号。

    样例一

    input

    1
    3 3
    1 2
    2 3
    1 3
    
    

    output

    YES
    1 2 -3
    
    

    样例二

    input

    2
    5 6
    2 3
    2 5
    3 4
    1 2
    4 2
    5 1
    
    

    output

    YES
    4 1 3 5 2 6
    
    

    限制与约定

    1n10^5,0m2×10^5

    时间限制1s

    空间限制256MB

    【分析】

      这是欧拉回路的模板题。

      主要是这样:

      无向图:所有点的度数都为偶数,一定有欧拉回路,从任意一个点开始都可以。

      有向图:所有点的入度=出度,一定有欧拉回路,从任意一个点开始都可以。

      我们不断走边,边没打过标记的就走,经过一条边就打标记,表示不能走这条边了,然后回溯的时候把路径记录下来,反着输出就可以。

      走过的边不仅要打标记(主要是无向图的反向边要标记一下),还要删除,不然即使不再走这条边也会不断询问它而导致TLE,

      解决方法是改变边目录的first数组,表示前面访问过的边都不用再继续访问了。

      

    void ffind(int x)
    {
    	vis[x]=1;
    	for(int i=first[x];i;i=first[x]) if(t[i].p)
    	{
    		int y=t[i].y;
    		t[i].p=t[t[i].o].p=0;
    		first[x]=t[i].next;
    		ffind(y);
    		op[++op[0]]=t[i].id;
    	}
    	else first[x]=t[i].next;
    }
    

      核心代码如上。

      【GDXB当初告诉我这叫套圈算法?

      【主要是回溯那里还有删边那里要记得。

     1 #include<cstdio>
     2 #include<cstdlib>
     3 #include<cstring>
     4 #include<iostream>
     5 #include<algorithm>
     6 #include<queue>
     7 #include<stack>
     8 using namespace std;
     9 #define Maxm 200010
    10 #define Maxn 100010
    11 
    12 struct node
    13 {
    14     int x,y,c,next,o;
    15     int id;
    16     bool p;
    17 }t[2*Maxm];
    18 int first[Maxn],len;
    19 int T;
    20 
    21 void ins(int x,int y,int id)
    22 {
    23     t[++len].x=x;t[len].y=y;t[len].p=1;
    24     t[len].id=id;t[len].next=first[x];first[x]=len;
    25     if(T==1) t[len].o=len&1?len+1:len-1;
    26     else t[len].o=len;
    27 }
    28 
    29 int rd[Maxn],cd[Maxn],op[Maxm];
    30 bool nw=0,vis[Maxn];
    31 
    32 void ffind(int x)
    33 {
    34     vis[x]=1;
    35     for(int i=first[x];i;i=first[x]) if(t[i].p)
    36     {
    37         int y=t[i].y;
    38         t[i].p=t[t[i].o].p=0;
    39         first[x]=t[i].next;
    40         ffind(y);
    41         op[++op[0]]=t[i].id;
    42     }
    43     else first[x]=t[i].next;
    44 }
    45 
    46 int main()
    47 {
    48     scanf("%d",&T);
    49     int n,m;
    50     scanf("%d%d",&n,&m);
    51     len=0;
    52     memset(first,0,sizeof(first));
    53     memset(rd,0,sizeof(rd));
    54     memset(cd,0,sizeof(cd));
    55     for(int i=1;i<=m;i++)
    56     {
    57         int x,y;
    58         scanf("%d%d",&x,&y);
    59         rd[y]++;cd[x]++;
    60         ins(x,y,i);
    61         if(T==1) ins(y,x,-i);
    62     }
    63     bool ok=1;
    64     for(int i=1;i<=n;i++) if(T==1&&(rd[i]+cd[i])%2!=0) {ok=0;break;}
    65     for(int i=1;i<=n;i++) if(T==2&&rd[i]!=cd[i]) {ok=0;break;}
    66     op[0]=0;
    67     if(!ok) printf("NO
    ");
    68     else
    69     {
    70         for(int i=1;i<=n;i++) vis[i]=0;
    71         for(int i=1;i<=n;i++)
    72         {
    73             ffind(i);
    74             if(op[0]!=0) break;
    75         }
    76         if(T==1&&op[0]!=len/2) printf("NO
    ");
    77         else if(T==2&&op[0]!=len) printf("NO
    ");
    78         else
    79         {
    80             printf("YES
    ");
    81             for(int i=op[0];i>=1;i--)
    82             {
    83                 printf("%d ",op[i]);
    84             }
    85             printf("
    ");
    86         }
    87         
    88     }
    89     return 0;
    90 }
    View Code

    2017-03-02 21:09:04

  • 相关阅读:
    IOS开发 网络发展史(NSURLProtocol)
    IOS开发 网络发展史(NSURLCach)
    IOS 开发 网络发展史(URLConnection)
    ios 网络开发(CFNetwork)
    MAC安装mysql
    conda 安装常用包
    从必应上拉取图片
    旋转数组中的二分查找
    东北大学 python模拟登录校园网(2019年6月启用新登录模式后)
    Ubuntu 安装Codeblocks
  • 原文地址:https://www.cnblogs.com/Konjakmoyu/p/6492567.html
Copyright © 2011-2022 走看看