codeforces CF36E Two Paths 欧拉回路

$ \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;
}
posted @ 2018-08-06 19:11  potrem  阅读(392)  评论(0编辑  收藏  举报