codeforces CF36E Two Paths 欧拉回路

$ \rightarrow $ 戳我进CF原题

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

  • $ 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;
}

猜你喜欢

转载自www.cnblogs.com/PotremZ/p/9432035.html