zoukankan      html  css  js  c++  java
  • codeforces CF36E Two Paths 欧拉回路

    博客迁移计划6

    $ \rightarrow $ 戳我进CF原题

    E. Two Paths


    time limit per test: 2 seconds
    memory limit per test: 64 megabytes
    input: input.txt
    output: output.txt

    Once archaeologists found $ m $ mysterious papers, each of which had a pair of integers written on them.
    Ancient people were known to like writing down the indexes of the roads they walked along,
    as « $ a \quad b $ » or « $ b \quad a $ » , where $ a,b $ are the indexes of two different cities joint by the road .
    It is also known that the mysterious papers are pages of two travel journals
    (those days a new journal was written for every new journey).
     
    During one journey the traveler could walk along one and the same road several times in one or several directions
    but in that case he wrote a new entry for each time in his journal. Besides,
    the archaeologists think that the direction the traveler took on a road had no effect upon the entry:
    the entry that looks like « $ a \quad b $ » could refer to the road from $ a $ to $ b $ as well as to the road from $ b $ to $ a $ .
     
    The archaeologists want to put the pages in the right order and reconstruct the two travel paths but unfortunately,
    they are bad at programming. That’s where you come in. Go help them!
     

    Input

    The first input line contains integer $ m (1 \le m \le 10000) $.
    Each of the following m lines describes one paper. Each description consists of two integers $ a,b ( 1\le a,b \le 10000,a \not= b) $ .
     

    Output

    In the first line output the number $ L_i $ . That is the length of the first path, i.e. the amount of papers in its description.
    In the following line output $ L_1 $ space-separated numbers — the indexes of the papers that describe the first path.
    In the third and fourth lines output similarly the length of the second path $ L_2 $ and the path itself.
    Both paths must contain at least one road, i.e. condition $ L_1>0 $ and $ L_2>0 $ must be met.
    The papers are numbered from $ 1 $ to $ m $ according to the order of their appearance in the input file.
    The numbers should be output in the order in which the traveler passed the corresponding roads.
    If the answer is not unique, output any.
     
    If it’s impossible to find such two paths, output «-1».
     
    Don’t forget that each paper should be used exactly once, i.e $ L_1+L_2=m $ .
     

    Examples

    input1

     2
     4 5
     4 3 
    

    output1

     1
     2
     1
     1
    

    input2

     1
     1 2
    

    output2

     -1
    

    题目大意

    • 在无向图中找到两条路径,一共经过每条边恰好一次。

    • $ n,m \le 10000 $

    题解

    • 连通块个数 $ >2 $ ,无解

    • 某个连通块奇度数点 $ >4 $ 个,无解

    • 连通块个数 $ =2 $ 并且其中一个连通块奇度数点 $ =4 $ 个,无解

    • 连通块个数 $ =1 $,奇度点个数 $ =4 $,在两个奇度点之间加一条虚边,求欧拉路,再断开

    • 其他情况,直接求欧拉路或欧拉回路

    代码

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cstring>
    #include<vector>
    using namespace std;
    #define maxn 10005
    struct edge{ int v,id,nxt; }e[maxn<<1];
    int head[maxn],tot=1;
    void add(int u,int v,int num){
        e[++tot].v=v; e[tot].id=num; e[tot].nxt=head[u]; head[u]=tot; 
    }
    int m,cnt,deg[maxn];
    vector<int>pr[maxn];
    bool vis[maxn];
    void dfs1(int u){
        vis[u]=1;
        if(deg[u]&1) pr[cnt].push_back(u);
        for(int i=head[u];i;i=e[i].nxt)
            if(!vis[e[i].v]) dfs1(e[i].v);
    }
    int cut,top,s[maxn];
    bool used[maxn],pr4;
    void dfs2(int u){
        for(int i=head[u];i;i=e[i].nxt)
            if(!used[e[i].id]){
                used[e[i].id]=1;
                dfs2(e[i].v);
                s[++top]=e[i].id;
                if(e[i].id==m&&pr4) cut=top; 
            }
    }
    int minu=maxn,cnt2st;
    bool pot[maxn];
    int main(){
        freopen("input.txt","r",stdin); 
        freopen("output.txt","w",stdout);
        scanf("%d",&m);
        for(int u,v,i=1;i<=m;++i){
            scanf("%d %d",&u,&v);
            pot[u]=pot[v]=1;
            minu=min(minu,min(u,v));
            ++deg[u]; ++deg[v];
            add(u,v,i); add(v,u,i); 
        }
        if(m==1){ puts("-1"); return 0; } 
        for(int i=1;i<=10000;++i)
            if(!vis[i]&&pot[i]){
                ++cnt;
                if(cnt>2){ puts("-1"); return 0; }
                if(pr4){ puts("-1"); return 0; }
                dfs1(i);
                if(pr[cnt].size()>4){ puts("-1"); return 0; }
                if(pr[cnt].size()==4){
                    if(cnt>1){ puts("-1"); return 0; }
                    pr4=1;
                }
                if(cnt==2&&pr[2].size()==0) cnt2st=i;
            }
        if(pr4){
            add(pr[1][0],pr[1][1],m+1);
            add(pr[1][1],pr[1][0],m+1);
            ++m;
            dfs2(pr[1][2]);
            if(top!=m){ puts("-1"); return 0; }
            printf("%d\n",cut-1);
            for(int i=1;i<cut;++i) printf("%d ",s[i]);
            printf("\n%d\n",m-cut);
            for(int i=cut+1;i<=m;++i) printf("%d ",s[i]);
        } else {
            if(pr[1].size()) dfs2(pr[1][0]);
            else dfs2(minu);
            if(cnt==2){
                cut=top;
                if(pr[2].size()) dfs2(pr[2][0]);
                else dfs2(cnt2st);
                if(top!=m){ puts("-1"); return 0; }
                printf("%d\n",cut);
                for(int i=1;i<=cut;++i) printf("%d ",s[i]);
                printf("\n%d\n",m-cut);
                for(int i=cut+1;i<=m;++i) printf("%d ",s[i]);
            } else {
                if(top!=m){ puts("-1"); return 0; }
                puts("1");
                printf("%d ",s[1]);
                printf("\n%d\n",m-1);
                for(int i=2;i<=m;++i) printf("%d ",s[i]);
            }
        }
        return 0;
    }
    
  • 相关阅读:
    第七课 GDB调试 (下)
    设计模式之原型模式
    设计模式之再读重构
    设计模式之代理模式
    设计模式之建造者模式
    设计模式之模板方法模式
    设计模式之抽象工厂模式
    设计模式之工厂模式
    设计模式之单例模式
    设计模式之6大原则
  • 原文地址:https://www.cnblogs.com/Potrem/p/CF36E.html
Copyright © 2011-2022 走看看